Logo ROOT   master
Reference Guide
TDocParser.cxx
Go to the documentation of this file.
1 // @(#)root/html:$Id$
2 // Author: Axel Naumann 2007-01-09
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TDocParser.h"
13 
14 #include "Riostream.h"
15 #include "TBaseClass.h"
16 #include "TClass.h"
17 #include "TClassDocOutput.h"
18 #include "TDataMember.h"
19 #include "TDataType.h"
20 #include "TDatime.h"
21 #include "TDocDirective.h"
22 #include "TGlobal.h"
23 #include "THtml.h"
24 #include "TInterpreter.h"
25 #include "TMethod.h"
26 #include "TMethodArg.h"
27 #include "TPRegexp.h"
28 #include "TROOT.h"
29 #include "TSystem.h"
30 #include "TVirtualMutex.h"
31 #include <string>
32 
33 namespace {
34 
35  class TMethodWrapperImpl: public TDocMethodWrapper {
36  public:
37  TMethodWrapperImpl(TMethod* m, int overloadIdx):
38  fMeth(m), fOverloadIdx(overloadIdx) {}
39 
40  static void SetClass(const TClass* cl) { fgClass = cl; }
41 
42  const char* GetName() const { return fMeth->GetName(); }
43  ULong_t Hash() const { return fMeth->Hash();}
44  Int_t GetNargs() const { return fMeth->GetNargs(); }
45  virtual TMethod* GetMethod() const { return fMeth; }
46  Bool_t IsSortable() const { return kTRUE; }
47 
48  Int_t GetOverloadIdx() const { return fOverloadIdx; }
49 
50  Int_t Compare(const TObject *obj) const {
51  const TMethodWrapperImpl* m = dynamic_cast<const TMethodWrapperImpl*>(obj);
52  if (!m) return 1;
53 
54  Int_t ret = strcasecmp(GetName(), m->GetName());
55  if (ret == 0) {
56  if (GetNargs() < m->GetNargs()) return -1;
57  else if (GetNargs() > m->GetNargs()) return 1;
58  if (GetMethod()->GetClass()->InheritsFrom(m->GetMethod()->GetClass()))
59  return -1;
60  else
61  return 1;
62  }
63 
64  const char* l(GetName());
65  const char* r(m->GetName());
66  if (l[0] == '~' && r[0] == '~') {
67  ++l;
68  ++r;
69  }
70  TClass *lcl = 0;
71  TClass *rcl = 0;
72  if (fMeth->Property() & (kIsConstructor|kIsDestructor)) {
73  lcl = TClass::GetClass(l);
74  }
75  if (m->fMeth->Property() & (kIsConstructor|kIsDestructor)) {
76  rcl = TClass::GetClass(r);
77  }
78  if (lcl && fgClass->InheritsFrom(lcl)) {
79  if (rcl && fgClass->InheritsFrom(rcl)) {
80  if (lcl->InheritsFrom(rcl))
81  return -1;
82  else return 1;
83  } else return -1;
84  } else if (rcl && fgClass->InheritsFrom(rcl))
85  return 1;
86 
87  if (l[0] == '~') return -1;
88  if (r[0] == '~') return 1;
89  return (ret < 0) ? -1 : 1;
90  }
91 
92  private:
93  static const TClass* fgClass; // current class, defining inheritance sort order
94  TMethod* fMeth; // my method
95  Int_t fOverloadIdx; // this is the n-th overload
96  };
97 
98  const TClass* TMethodWrapperImpl::fgClass = 0;
99 }
100 
101 
102 //______________________________________________________________________________
103 ////////////////////////////////////////////////////////////////////////////////
104 //
105 // Parse C++ source or header, and extract documentation.
106 //
107 // Also handles special macros like
108 /* Begin_Macro(GUI, source)
109 {
110  TGMainFrame* f = new TGMainFrame(0, 100, 100);
111  f->SetName("testMainFrame"); // that's part of the name of the image
112  TGButton* b = new TGTextButton(f, "Test Button");
113  f->AddFrame(b);
114  f->MapSubwindows();
115  f->Resize(f->GetDefaultSize());
116 
117  f->MapWindow();
118  return f; // *HIDE*
119 }
120 End_Macro */
121 // or multiline Latex aligned at =:
122 /* Begin_Latex(separator='=',align=rcl) C = d #sqrt{#frac{2}{#lambdaD}} #int^{x}_{0}cos(#frac{#pi}{2}t^{2})dt
123  D(x) = d End_Latex */
124 // even without alignment: Begin_Latex
125 // x=sin^2(y)
126 // y = #sqrt{sin(x)}
127 // End_Latex and what about running an external macro?
128 /* BEGIN_MACRO(source)
129 
130 
131 testmacro.C END_MACRO
132 
133 
134 and some nested stuff which doesn't work yet: */
135 // BEGIN_HTML
136 /* BEGIN_LATEX Wow,^{an}_{image}^{inside}_{a}^{html}_{block}
137  END_LATEX
138 */
139 // END_HTML
140 ////////////////////////////////////////////////////////////////////////////////
141 
143 
144 std::set<std::string> TDocParser::fgKeywords;
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Constructor called for parsing class sources
148 
150  fHtml(docOutput.GetHtml()), fDocOutput(&docOutput), fLineNo(0),
151  fCurrentClass(cl), fRecentClass(0), fCurrentModule(0),
152  fDirectiveCount(0), fLineNumber(0), fDocContext(kIgnore),
153  fCheckForMethod(kFALSE), fClassDocState(kClassDoc_Uninitialized),
154  fCommentAtBOL(kFALSE), fAllowDirectives(kTRUE)
155 {
156  InitKeywords();
157 
161 
163 
164  TMethodWrapperImpl::SetClass(cl);
165 
166  for (int ia = 0; ia < 3; ++ia) {
167  fMethods[ia].Rehash(101);
168  }
169 
172 
173  // needed for list of methods,...
174  fParseContext.push_back(kCode);
175 
176  // create an array of method names
177  TMethod *method;
178  TIter nextMethod(fCurrentClass->GetListOfMethods());
179  fMethodCounts.clear();
180  while ((method = (TMethod *) nextMethod())) {
181  ++fMethodCounts[method->GetName()];
182  }
183 
184 }
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// constructor called for parsing text files with Convert()
188 
190  fHtml(docOutput.GetHtml()), fDocOutput(&docOutput), fLineNo(0),
191  fCurrentClass(0), fRecentClass(0), fDirectiveCount(0),
192  fLineNumber(0), fDocContext(kIgnore),
193  fCheckForMethod(kFALSE), fClassDocState(kClassDoc_Uninitialized),
194  fCommentAtBOL(kFALSE), fAllowDirectives(kFALSE)
195 {
196  InitKeywords();
197 
201 
203 
204  TMethodWrapperImpl::SetClass(0);
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// destructor, checking whether all methods have been found for gDebug > 3
209 
211 {
212  if (gDebug > 3) {
213  for (std::map<std::string, Int_t>::const_iterator iMethod = fMethodCounts.begin();
214  iMethod != fMethodCounts.end(); ++iMethod)
215  if (iMethod->second)
216  Info("~TDocParser", "Implementation of method %s::%s could not be found.",
218  iMethod->first.c_str());
219  TIter iDirective(&fDirectiveHandlers);
220  TDocDirective* directive = 0;
221  while ((directive = (TDocDirective*) iDirective())) {
222  TString directiveName;
223  directive->GetName(directiveName);
224  Warning("~TDocParser", "Missing \"%s\" for macro %s", directive->GetEndTag(), directiveName.Data());
225  }
226  }
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Add accessible (i.e. non-private) methods of base class bc
231 /// and its base classes' methods to methodNames.
232 /// If bc==0, we add fCurrentClass's methods (and also private functions).
233 
235 {
236  // make a loop on member functions
237  TClass *cl = fCurrentClass;
238  if (bc)
239  cl = bc->GetClassPointer(kFALSE);
240  if (!cl) return;
241 
242  TMethod *method;
243  TIter nextMethod(cl->GetListOfMethods());
244  std::map<std::string, int> methOverloads;
245 
246  while ((method = (TMethod *) nextMethod())) {
247 
248  if (!strcmp(method->GetName(), "Dictionary") ||
249  !strcmp(method->GetName(), "Class_Version") ||
250  !strcmp(method->GetName(), "Class_Name") ||
251  !strcmp(method->GetName(), "DeclFileName") ||
252  !strcmp(method->GetName(), "DeclFileLine") ||
253  !strcmp(method->GetName(), "ImplFileName") ||
254  !strcmp(method->GetName(), "ImplFileLine") ||
255  (bc && (method->GetName()[0] == '~' // d'tor
256  || !strcmp(method->GetName(), method->GetReturnTypeName()))) // c'tor
257  )
258  continue;
259 
260 
261  Int_t mtype = 0;
262  if (kIsPrivate & method->Property())
263  mtype = 0;
264  else if (kIsProtected & method->Property())
265  mtype = 1;
266  else if (kIsPublic & method->Property())
267  mtype = 2;
268 
269  if (bc) {
270  if (mtype == 0) continue;
271  if (bc->Property() & kIsPrivate)
272  mtype = 0;
273  else if ((bc->Property() & kIsProtected) && mtype == 2)
274  mtype = 1;
275  }
276 
277  Bool_t hidden = kFALSE;
278  for (Int_t access = 0; !hidden && access < 3; ++access) {
279  TMethodWrapperImpl* other = (TMethodWrapperImpl*) fMethods[access].FindObject(method->GetName());
280  hidden |= (other) && (other->GetMethod()->GetClass() != method->GetClass());
281  }
282  if (!hidden) {
283  fMethods[mtype].Add(new TMethodWrapperImpl(method, methOverloads[method->GetName()]));
284  ++methOverloads[method->GetName()];
285  }
286  }
287 
288  TIter iBase(cl->GetListOfBases());
289  TBaseClass* base = 0;
290  while ((base = (TBaseClass*)iBase()))
292 
293  if (!bc)
294  for (Int_t access = 0; access < 3; ++access) {
295  fMethods[access].SetOwner();
296  fMethods[access].Sort();
297  }
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Add data members of fCurrentClass and of bc to datamembers, recursively.
302 /// Real data members are in idx 0..2 (public, protected, private access),
303 /// enum constants in idx 3..5.
304 
306  // make a loop on member functions
307  TClass *cl = fCurrentClass;
308  if (bc)
309  cl = bc->GetClassPointer(kFALSE);
310  if (!cl) return;
311 
312  TDataMember *dm;
313  TIter nextDM(cl->GetListOfDataMembers());
314 
315  while ((dm = (TDataMember *) nextDM())) {
316  if (!strcmp(dm->GetName(), "fgIsA"))
317  continue;
318  Int_t mtype = 0;
319  if (kIsPrivate & dm->Property())
320  mtype = 0;
321  else if (kIsProtected & dm->Property())
322  mtype = 1;
323  else if (kIsPublic & dm->Property())
324  mtype = 2;
325 
326  if (bc) {
327  if (mtype == 0) continue;
328  if (bc->Property() & kIsPrivate)
329  mtype = 0;
330  else if ((bc->Property() & kIsProtected) && mtype == 2)
331  mtype = 1;
332  }
333 
334  const Int_t flagEnumConst = kIsEnum | kIsConstant | kIsStatic;
335  if ((dm->Property() & flagEnumConst) == flagEnumConst
336  && dm->GetDataType() && dm->GetDataType()->GetType() == kInt_t) {
337  mtype = 5;
338  // The access of the enum constant is defined by the access of the enum:
339  // for CINT, all enum constants are public.
340  // There is no TClass or TDataType for enum types; instead, use CINT:
341  /*
342  No - CINT does not know their access restriction.
343  With CINT5 we have no way of determining it...
344 
345  ClassInfo_t* enumCI = gInterpreter->ClassInfo_Factory(dm->GetTypeName());
346  if (enumCI) {
347  Long_t prop = gInterpreter->ClassInfo_Property(enumCI);
348  if (kIsPrivate & prop)
349  mtype = 3;
350  else if (kIsProtected & prop)
351  mtype = 4;
352  else if (kIsPublic & prop)
353  mtype = 5;
354  gInterpreter->ClassInfo_Delete(enumCI);
355  }
356  */
357  }
358 
359  fDataMembers[mtype].Add(dm);
360  }
361 
362  TIter iBase(cl->GetListOfBases());
363  TBaseClass* base = 0;
364  while ((base = (TBaseClass*)iBase()))
366 
367  if (!bc)
368  for (Int_t access = 0; access < 6; ++access) {
369  fDataMembers[access].SetOwner(kFALSE);
370  if (access < 3) // don't sort enums; we keep them in enum tag order
371  fDataMembers[access].Sort();
372  }
373 }
374 
375 
376 ////////////////////////////////////////////////////////////////////////////////
377 /// Create an anchor from the given line, by hashing it and
378 /// convertig the hash into a custom base64 string.
379 
381  const char base64String[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
382 
383  // use hash of line instead of e.g. line number.
384  // advantages: more stable (lines can move around, we still find them back),
385  // no need for keeping a line number context
386  UInt_t hash = ::Hash(line);
387  anchor.Remove(0);
388  // force first letter to be [A-Za-z], to be id compatible
389  anchor += base64String[hash % 52];
390  hash /= 52;
391  while (hash) {
392  anchor += base64String[hash % 64];
393  hash /= 64;
394  }
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// Parse text file "in", add links etc, and write output to "out".
399 /// If "isCode", "in" is assumed to be C++ code.
400 
401 void TDocParser::Convert(std::ostream& out, std::istream& in, const char* relpath,
402  Bool_t isCode, Bool_t interpretDirectives)
403 {
404  fLineNumber = 0;
405  fParseContext.clear();
406  if (isCode) fParseContext.push_back(kCode);
407  else fParseContext.push_back(kComment); // so we can find "BEGIN_HTML"/"END_HTML" in plain text
408 
409  while (!in.eof()) {
410  fLineRaw.ReadLine(in, kFALSE);
411  ++fLineNumber;
412  if (in.eof())
413  break;
414 
415  // remove leading spaces
416  fLineComment = "";
420 
422 
423  // Changes in this bit of code have consequences for:
424  // * module index,
425  // * source files,
426  // * THtml::Convert() e.g. in tutorials/html/MakeTutorials.C
427  if (!interpretDirectives) {
428  // Only write the raw, uninterpreted directive code:
429  if (!InContext(kDirective)) {
431  out << fLineSource << std::endl;
432  }
433  } else {
434  // Write source for source and interpreted directives if they exist.
435  if (fLineComment.Length() ) {
437  out << fLineComment << std::endl;
438  } else if (!InContext(kDirective)) {
440  out << fLineSource << std::endl;
441  }
442  }
443  }
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Expand keywords in text, writing to out.
448 
449 void TDocParser::DecorateKeywords(std::ostream& out, const char *text)
450 {
451  TString str(text);
452  DecorateKeywords(str);
453  out << str;
454 }
455 
456 ////////////////////////////////////////////////////////////////////////////////
457 /// Find keywords in line and create URLs around them. Escape characters with a
458 /// special meaning for HTML. Protect "Begin_Html"/"End_Html" pairs, and set the
459 /// parsing context. Evaluate sequences like a::b->c.
460 /// Skip regions where directives are active.
461 
463 {
464  std::list<TClass*> currentType;
465 
466  enum {
467  kNada,
468  kMember,
469  kScope,
470  kNumAccesses
471  } scoping = kNada;
472 
473  currentType.push_back(0);
474 
475  Ssiz_t i = 0;
476  while (isspace((UChar_t)line[i]))
477  ++i;
478 
479  Ssiz_t startOfLine = i;
480 
481  // changed when the end of a directive is encountered, i.e.
482  // from where fLineSource needs to be appended to fLineComment
483  Ssiz_t copiedToCommentUpTo = 0;
484 
486  // we're only waiting for an "End_Whatever" and ignoring everything else
488  const char* endTag = directive->GetEndTag();
489  Ssiz_t posEndTag = i;
490  while (kNPOS != (posEndTag = line.Index(endTag, posEndTag, TString::kIgnoreCase)))
491  if (posEndTag == 0 || line[posEndTag - 1] != '"') // escaping '"'
492  break;
493  if (posEndTag != kNPOS)
494  i = posEndTag;
495  else {
496  Ssiz_t start = 0;
498  // means we are in a C++ comment
499  while (isspace((UChar_t)fLineRaw[start])) ++start;
500  if (fLineRaw[start] == '/' && fLineRaw[start + 1] == '/')
501  start += 2;
502  else start = 0;
503  }
504  directive->AddLine(fLineRaw(start, fLineRaw.Length()));
505  while(i < line.Length())
507  copiedToCommentUpTo = i;
508  }
509  }
510 
511  for (; i < line.Length(); ++i) {
512 
513  if (!currentType.back())
514  scoping = kNada;
515 
516  // evaluate scope relation
517  if (Context() == kCode
518  || Context() == kComment) {
519  if (currentType.back())
520  switch (line[i]) {
521  case ':':
522  if (line[i + 1] == ':') {
523  scoping = kScope;
524  i += 1;
525  continue;
526  }
527  break;
528  case '-':
529  if (line[i + 1] == '>') {
530  scoping = kMember;
531  i += 1;
532  continue;
533  }
534  break;
535  case '.':
536  if (line[i + 1] != '.') {
537  // prevent "..."
538  scoping = kMember;
539  continue;
540  }
541  break;
542  }
543  switch (line[i]) {
544  case '(':
545  currentType.push_back(0);
546  scoping = kNada;
547  continue;
548  break;
549  case ')':
550  if (currentType.size() > 1)
551  currentType.pop_back();
552  scoping = kMember;
553  continue;
554  break;
555  }
556  if (i >= line.Length())
557  break;
558  } else // code or comment
559  currentType.back() = 0;
560 
561 
562  if (!IsWord(line[i])){
563 
564  Bool_t haveHtmlEscapedChar = Context() == kString
565  && i > 2 && line[i] == '\'' && line[i-1] == ';';
566  if (haveHtmlEscapedChar) {
567  Ssiz_t posBegin = i - 2;
568  while (posBegin > 0 && IsWord(line[posBegin]))
569  --posBegin;
570  haveHtmlEscapedChar = posBegin > 0 &&
571  line[posBegin] == '&' && line[posBegin - 1] == '\'';
572  }
573  EParseContext context = Context();
574  Bool_t closeString = context == kString
575  && ( line[i] == '"'
576  || (line[i] == '\''
577  && ( (i > 1 && line[i - 2] == '\'')
578  || (i > 3 && line[i - 2] == '\\' && line[i - 3] == '\'')))
579  || haveHtmlEscapedChar)
580  && (i == 0 || line[i - 1] != '\\'); // but not "foo \"str...
581  if (context == kCode || context == kComment) {
582  if (line[i] == '"' || (line[i] == '\'' && (
583  // 'a'
584  (line.Length() > i + 2 && line[i + 2] == '\'') ||
585  // '\a'
586  (line.Length() > i + 3 && line[i + 1] == '\'' && line[i + 3] == '\'')))) {
587 
589  fParseContext.push_back(kString);
590  currentType.back() = 0;
591  closeString = kFALSE;
592  } else if (context == kCode
593  && line[i] == '/' && (line[i+1] == '/' || line[i+1] == '*')) {
594  fParseContext.push_back(kComment);
595  if (line[i+1] == '/')
596  fParseContext.back() |= kCXXComment;
597  currentType.back() = 0;
599  ++i;
600  } else if (context == kComment
601  && !(fParseContext.back() & kCXXComment)
602  && line.Length() > i + 1
603  && line[i] == '*' && line[i+1] == '/') {
604  if (fParseContext.size()>1)
605  fParseContext.pop_back();
606 
607  currentType.back() = 0;
608  i += 2;
610  if (!fCommentAtBOL) {
611  if (InContext(kDirective))
612  ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(line(copiedToCommentUpTo, i));
613  else
614  fLineComment += line(copiedToCommentUpTo, i);
615  copiedToCommentUpTo = i;
616  }
617  } else if (startOfLine == i
618  && line[i] == '#'
619  && context == kCode) {
620  ExpandCPPLine(line, i);
621  }
622  } // if context is comment or code
623 
624  if (i < line.Length())
626 
627  if (closeString) {
629  if (fParseContext.size()>1)
630  fParseContext.pop_back();
631 
632  currentType.back() = 0;
633  }
634  --i; // i already moved by ReplaceSpecialChar
635 
636  continue;
637  } // end of "not a word"
638 
639  // get the word
640  Ssiz_t endWord = i;
641  while (endWord < line.Length() && IsName(line[endWord]))
642  endWord++;
643 
644  if (Context() == kString || Context() == kCPP) {
645  // don't replace in strings, cpp, etc
646  i = endWord - 1;
647  continue;
648  }
649 
650  TString word(line(i, endWord - i));
651 
652  // '"' escapes handling of "Begin_..."/"End_..."
653  if ((i == 0 || (i > 0 && line[i - 1] != '"'))
654  && HandleDirective(line, i, word, copiedToCommentUpTo)) {
655  // something special happened; the currentType is gone.
656  currentType.back() = 0;
657  continue;
658  }
659 
660  // don't replace keywords in comments
661  if (Context() == kCode
662  && fgKeywords.find(word.Data()) != fgKeywords.end()) {
664  i += word.Length();
666  --i; // -1 for ++i
667  currentType.back() = 0;
668  continue;
669  }
670 
671  // Now decorate scopes and member, referencing their documentation:
672 
673  // generic layout:
674  // A::B::C::member[arr]->othermember
675  // we iterate through this, first scope is A, and currentType will be set toA,
676  // next we see ::B, "::" signals to use currentType,...
677 
678  TDataType* subType = 0;
679  TClass* subClass = 0;
680  TDataMember *datamem = 0;
681  TMethod *meth = 0;
682  const char* globalTypeName = 0;
683  if (currentType.empty()) {
684  Warning("DecorateKeywords", "type context is empty!");
685  currentType.push_back(0);
686  }
687  TClass* lookupScope = currentType.back();
688 
689  if (scoping == kNada) {
690  if (fCurrentClass)
691  lookupScope = fCurrentClass;
692  else
693  lookupScope = fRecentClass;
694  }
695 
696  if (scoping == kNada) {
697  subType = gROOT->GetType(word);
698  if (!subType)
699  subClass = fHtml->GetClass(word);
700  if (!subType && !subClass) {
701  TGlobal *global = gROOT->GetGlobal(word);
702  if (global) {
703  // cannot doc globals; take at least their type...
704  globalTypeName = global->GetTypeName();
705  subClass = fHtml->GetClass(globalTypeName);
706  if (!subClass)
707  subType = gROOT->GetType(globalTypeName);
708  else // hack to prevent current THtml obj from showing up - we only want gHtml
709  if (subClass == THtml::Class() && word != "gHtml")
710  subClass = 0;
711  }
712  }
713  if (!subType && !subClass) {
714  // too bad - cannot doc yet...
715  //TFunction *globFunc = gROOT->GetGlobalFunctionWithPrototype(word);
716  //globFunc = 0;
717  }
718  if (!subType && !subClass) {
719  // also try template
720  while (isspace(line[endWord])) ++endWord;
721  if (line[endWord] == '<' || line[endWord] == '>') {
722  // check for possible template
723  Ssiz_t endWordT = endWord + 1;
724  int templateLevel = 1;
725  while (endWordT < line.Length()
726  && (templateLevel
727  || IsName(line[endWordT])
728  || line[endWordT] == '<'
729  || line[endWordT] == '>')) {
730  if (line[endWordT] == '<')
731  ++templateLevel;
732  else if (line[endWordT] == '>')
733  --templateLevel;
734  endWordT++;
735  }
736  subClass = fHtml->GetClass(line(i, endWordT - i).Data());
737  if (subClass)
738  word = line(i, endWordT - i);
739  }
740  }
741  }
742 
743  if (lookupScope && !subType && !subClass) {
744  if (scoping == kScope) {
745  TString subClassName(lookupScope->GetName());
746  subClassName += "::";
747  subClassName += word;
748  subClass = fHtml->GetClass(subClassName);
749  if (!subClass)
750  subType = gROOT->GetType(subClassName);
751  }
752  if (!subClass && !subType) {
753  // also try A::B::c()
754  datamem = lookupScope->GetDataMember(word);
755  if (!datamem)
756  meth = lookupScope->GetMethodAllAny(word);
757  }
758  if (!subClass && !subType && !datamem && !meth) {
759  // also try template
760  while (isspace(line[endWord])) ++endWord;
761  if (line[endWord] == '<' || line[endWord] == '>') {
762  // check for possible template
763  Ssiz_t endWordT = endWord + 1;
764  int templateLevel = 1;
765  while (endWordT < line.Length()
766  && (templateLevel
767  || IsName(line[endWordT])
768  || line[endWordT] == '<'
769  || line[endWordT] == '>')) {
770  if (line[endWordT] == '<')
771  ++templateLevel;
772  else if (line[endWordT] == '>')
773  --templateLevel;
774  endWordT++;
775  }
776  TString subClassName(lookupScope->GetName());
777  subClassName += "::";
778  subClassName += line(i, endWordT - i);
779  subClass = fHtml->GetClass(subClassName);
780  if (subClass)
781  word = line(i, endWordT - i);
782  }
783  }
784  }
785  // create the link
786  TString mangledWord(word);
787  fDocOutput->ReplaceSpecialChars(mangledWord);
788  line.Replace(i, word.Length(), mangledWord);
789 
790  TSubString substr(line(i, mangledWord.Length()));
791  if (subType) {
792  fDocOutput->ReferenceEntity(substr, subType,
793  globalTypeName ? globalTypeName : subType->GetName());
794  currentType.back() = 0;
795  } else if (subClass) {
796  fDocOutput->ReferenceEntity(substr, subClass,
797  globalTypeName ? globalTypeName : subClass->GetName());
798 
799  currentType.back() = subClass;
800  fRecentClass = subClass;
801  } else if (datamem || meth) {
802  if (datamem) {
803  fDocOutput->ReferenceEntity(substr, datamem);
804 
805  if (datamem->GetTypeName())
806  currentType.back() = fHtml->GetClass(datamem->GetTypeName());
807  } else {
808  fDocOutput->ReferenceEntity(substr, meth);
809 
810  TString retTypeName = meth->GetReturnTypeName();
811  if (retTypeName.BeginsWith("const "))
812  retTypeName.Remove(0,6);
813  Ssiz_t pos=0;
814  while (IsWord(retTypeName[pos]) || retTypeName[pos]=='<' || retTypeName[pos]=='>' || retTypeName[pos]==':')
815  ++pos;
816  retTypeName.Remove(pos, retTypeName.Length());
817  if (retTypeName.Length())
818  currentType.back() = fHtml->GetClass(retTypeName);
819  }
820  } else
821  currentType.back() = 0;
822 
823  //i += mangledWord.Length();
824  i += substr.Length();
825 
826  --i; // due to ++i
827  } // while i < line.Length()
828  if (i > line.Length())
829  i = line.Length();
830 
831  // clean up, no strings across lines
832  if (Context() == kString) {
834  if (fParseContext.size()>1)
835  fParseContext.pop_back();
836  currentType.back() = 0;
837  }
838 
839  // HandleDirective already copied the chunk before the directive
840  // from fLineSource to fLineComment. So we're done up to "i" in
841  // fLineSource; next time we encounter a directive we just need
842  // to copy from startOfComment on.
843  if ((InContext(kComment) || fCommentAtBOL) && copiedToCommentUpTo < line.Length()) {
844  if (InContext(kDirective))
845  ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(line(copiedToCommentUpTo, line.Length()));
846  else
847  fLineComment += line(copiedToCommentUpTo, line.Length());
848  }
849 
850  // Do this after we append to fLineComment, otherwise the closing
851  // </span> gets sent to the directive.
852  // clean up, no CPP comment across lines
853  if (InContext(kComment) & kCXXComment) {
855  if (fLineComment.Length()) {
856  Ssiz_t pos = fLineComment.Length();
858  }
860  currentType.back() = 0;
861  }
862 }
863 
864 ////////////////////////////////////////////////////////////////////////////////
865 /// reduce method count for method called name,
866 /// removing it from fMethodCounts once the count reaches 0.
867 
869 {
870  typedef std::map<std::string /*method name*/, Int_t > MethodCount_t;
871  MethodCount_t::iterator iMethodName = fMethodCounts.find(name);
872  if (iMethodName != fMethodCounts.end()) {
873  --(iMethodName->second);
874  if (iMethodName->second <= 0)
875  fMethodCounts.erase(iMethodName);
876  }
877 }
878 
879 ////////////////////////////////////////////////////////////////////////////////
880 /// Delete output generated by prior runs of all known directives;
881 /// the output file names might have changes.
882 
884 {
885  TIter iClass(gROOT->GetListOfClasses());
886  TClass* cl = 0;
887  while ((cl = (TClass*) iClass()))
888  if (cl != TDocDirective::Class()
889  && cl->InheritsFrom(TDocDirective::Class())) {
890  TDocDirective* directive = (TDocDirective*) cl->New();
891  if (!directive) continue;
892  directive->SetParser(const_cast<TDocParser*>(this));
893  directive->DeleteOutput();
894  delete directive;
895  }
896 }
897 
898 ////////////////////////////////////////////////////////////////////////////////
899 /// Expand preprocessor statements
900 ///
901 ///
902 /// Input: line - line containing the CPP statement,
903 /// pos - position of '#'
904 ///
905 /// NOTE: Looks for the #include statements and
906 /// creates link to the corresponding file
907 /// if such file exists
908 ///
909 
911 {
912  Bool_t linkExist = kFALSE;
913  Ssiz_t posEndOfLine = line.Length();
914  Ssiz_t posHash = pos;
915 
916  Ssiz_t posInclude = line.Index("include", pos);
917  if (posInclude != kNPOS) {
918  TString filename;
919  Ssiz_t posStartFilename = posInclude + 7;
920  if (line.Tokenize(filename, posStartFilename, "[<\"]")) {
921  Ssiz_t posEndFilename = posStartFilename;
922  if (line.Tokenize(filename, posEndFilename, "[>\"]")) {
924 
925  TString filesysFileName;
926  if (fHtml->GetPathDefinition().GetFileNameFromInclude(filename, filesysFileName)) {
927  fDocOutput->CopyHtmlFile(filesysFileName);
928 
929  TString endOfLine(line(posEndFilename - 1, line.Length()));
930  line.Remove(posStartFilename, line.Length());
931  for (Ssiz_t i = pos; i < line.Length();)
933 
934  line += "<a href=\"./";
935  line += gSystem->BaseName(filename);
936  line += "\">";
937  line += filename + "</a>" + endOfLine[0]; // add include file's closing '>' or '"'
938  posEndOfLine = line.Length() - 1; // set the "processed up to" to it
939  fDocOutput->ReplaceSpecialChars(line, posEndOfLine); // and run replace-special-char on it
940 
941  line += endOfLine(1, endOfLine.Length()); // add the unprocessed part of the line back
942 
943  linkExist = kTRUE;
944  }
945  }
946  }
947  }
948 
949  if (!linkExist) {
951  posEndOfLine = line.Length();
952  }
953 
954  Ssiz_t posHashAfterDecoration = posHash;
955  fDocOutput->DecorateEntityBegin(line, posHashAfterDecoration, kCPP);
956  posEndOfLine += posHashAfterDecoration - posHash;
957 
958  fDocOutput->DecorateEntityEnd(line, posEndOfLine, kCPP);
959  pos = posEndOfLine;
960 }
961 
962 
963 ////////////////////////////////////////////////////////////////////////////////
964 /// Return the name of module for which sources are currently parsed.
965 
966 void TDocParser::GetCurrentModule(TString& out_module) const {
967  if (fCurrentModule) out_module = fCurrentModule;
968  else if (fCurrentClass) fHtml->GetModuleNameForClass(out_module, fCurrentClass);
969  else out_module = "(UNKNOWN MODULE WHILE PARSING)";
970 }
971 
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Process directives to the documentation engine, like "Begin_Html" / "End_Html",
974 /// "Begin_Macro" / "End_Macro", and "Begin_Latex" / "End_Latex".
975 
977  Ssiz_t& copiedToCommentUpTo)
978 {
979  Bool_t begin = kTRUE;
980  TClass* clDirective = IsDirective(line, pos, word, begin);
981  if (!clDirective)
982  return kFALSE;
983 
984  // we'll need end later on: afer the begin block, both end _and_ begin can be true.
985  Bool_t end = !begin;
986 
987  TDocDirective* directive = 0; // allow re-use of object from begin block in end
988 
989  if (begin) {
990  // copy from fLineSource to fLineComment, starting at copiedToCommentUpTo
991  if (InContext(kDirective))
992  ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(fLineSource(copiedToCommentUpTo, pos - copiedToCommentUpTo));
993  else
994  fLineComment += fLineSource(copiedToCommentUpTo, pos - copiedToCommentUpTo);
995  copiedToCommentUpTo = pos;
996 
997  pos += word.Length(); // skip the keyword
998 
999  directive = (TDocDirective*) clDirective->New();
1000  if (!directive)
1001  return kFALSE;
1002 
1003  directive->SetParser(this);
1004  if (fCurrentMethodTag.Length())
1005  directive->SetTag(fCurrentMethodTag);
1006  directive->SetCounter(fDirectiveCount++);
1007 
1008  // parse parameters
1009  TString params;
1010  if (begin && line[pos] == '(') {
1011  std::list<char> waitForClosing;
1012  Ssiz_t endParam = pos + 1;
1013  for (; endParam < line.Length()
1014  && (line[endParam] != ')' || !waitForClosing.empty()); ++endParam) {
1015  const char c = line[endParam];
1016  if (!waitForClosing.empty() && waitForClosing.back() == c) {
1017  waitForClosing.pop_back();
1018  continue;
1019  }
1020  switch (c) {
1021  case '"':
1022  if (waitForClosing.empty() || waitForClosing.back() != '\'')
1023  waitForClosing.push_back('"');
1024  break;
1025  case '\'':
1026  if (waitForClosing.empty() || waitForClosing.back() != '"')
1027  waitForClosing.push_back('\'');
1028  break;
1029  case '(':
1030  if (waitForClosing.empty() || (waitForClosing.back() != '"' && waitForClosing.back() != '\''))
1031  waitForClosing.push_back(')');
1032  break;
1033  case '\\':
1034  ++endParam; // skip next char
1035  default:
1036  break;
1037  };
1038  }
1039  if (waitForClosing.empty()) {
1040  params = line(pos + 1, endParam - (pos + 1));
1041  pos += params.Length() + 2; // params + parentheses
1042  }
1043  directive->SetParameters(params);
1044  }
1045 
1046  // check for end tag in current line
1047  Ssiz_t posEndTag = pos;
1048  const char* endTag = directive->GetEndTag();
1049  Ssiz_t lenEndTag = strlen(endTag);
1050  while (kNPOS != (posEndTag = line.Index(endTag, posEndTag, TString::kIgnoreCase))) {
1051  if (line[posEndTag - 1] == '"') {
1052  posEndTag += lenEndTag;
1053  continue; // escaping '"'
1054  }
1055  break;
1056  }
1057  if (posEndTag != kNPOS) {
1058  end = kTRUE; // we just continue below!
1059  } else {
1060  fDirectiveHandlers.AddLast(directive);
1061 
1062  fParseContext.push_back(kDirective);
1064  fParseContext.back() |= kCXXComment;
1065 
1066  posEndTag = line.Length();
1067  }
1068 
1069  directive->AddLine(line(pos, posEndTag - pos));
1070  TString remainder(line(posEndTag, line.Length()));
1071  line.Remove(posEndTag, line.Length());
1072 
1073  while (pos < line.Length())
1075 
1076  pos = line.Length();
1077  // skip the remainder of the line
1078  copiedToCommentUpTo = line.Length();
1079  line += remainder;
1080  }
1081 
1082  // no else - "end" can also be set by begin having an end tag!
1083  if (end) {
1084 
1085  if (!begin)
1086  pos += word.Length(); // skip the keyword
1087  else pos += word.Length() - 2; // "Begin" is 2 chars longer than "End"
1088 
1089  if (!directive) directive = (TDocDirective*) fDirectiveHandlers.Last();
1090 
1091  if (!directive) {
1092  Warning("HandleDirective", "Cannot find directive handler object %s !",
1093  fLineRaw.Data());
1094  return kFALSE;
1095  }
1096 
1097  if (!begin) {
1098  Ssiz_t start = 0;
1100  // means we are in a C++ comment
1101  while (isspace((UChar_t)fLineRaw[start])) ++start;
1102  if (fLineRaw[start] == '/' && fLineRaw[start + 1] == '/')
1103  start += 2;
1104  else start = 0;
1105  }
1106  directive->AddLine(line(start, pos - word.Length() - start));
1107 
1108  TString remainder(line(pos, line.Length()));
1109  line.Remove(pos, line.Length());
1111  pos = line.Length();
1112  line += remainder;
1113  }
1114  copiedToCommentUpTo = pos;
1115 
1116  TString result;
1117  directive->GetResult(result);
1118 
1119  if (!begin)
1121  delete directive;
1122 
1123  if (!begin) {
1124  // common to all directives: pop context
1125  Bool_t isInCxxComment = InContext(kDirective) & kCXXComment;
1126  if (fParseContext.size()>1)
1127  fParseContext.pop_back();
1128  if (isInCxxComment && !InContext(kComment)) {
1129  fParseContext.push_back(kComment | kCXXComment);
1131  }
1132  }
1133 
1135  ((TDocDirective*)fDirectiveHandlers.Last())->AddLine(result(0, result.Length()));
1136  else
1137  fLineComment += result;
1138 
1139  /* NO - this can happen e.g. for "BEGIN_HTML / *..." (see doc in this class)
1140  if (Context() != kComment) {
1141  Warning("HandleDirective", "Popping back a directive context, but enclosing context is not a comment! At:\n%s",
1142  fLineRaw.Data());
1143  fParseContext.push_back(kComment);
1144  }
1145  */
1146  }
1147 
1148  return kTRUE;
1149 }
1150 
1151 ////////////////////////////////////////////////////////////////////////////////
1152 /// checks whether we are in a parse context, return the entry closest
1153 /// to the current context.
1154 /// If context is a EParseContextFlag just look for the first match in
1155 /// the flags
1156 
1158 {
1159  UInt_t lowerContext = context & kParseContextMask;
1160  UInt_t contextFlag = context & kParseContextFlagMask;
1161 
1162  for (std::list<UInt_t>::const_reverse_iterator iPC = fParseContext.rbegin();
1163  iPC != fParseContext.rend(); ++iPC)
1164  if (!lowerContext || ((lowerContext && ((*iPC & kParseContextMask) == lowerContext))
1165  && (!contextFlag || (contextFlag && (*iPC & contextFlag)))))
1166  return *iPC;
1167 
1168  return 0;
1169 }
1170 
1171 ////////////////////////////////////////////////////////////////////////////////
1172 /// fill C++ keywords into fgKeywords
1173 
1175 {
1176  if (!fgKeywords.empty())
1177  return;
1178 
1179  fgKeywords.insert("asm");
1180  fgKeywords.insert("auto");
1181  fgKeywords.insert("bool");
1182  fgKeywords.insert("break");
1183  fgKeywords.insert("case");
1184  fgKeywords.insert("catch");
1185  fgKeywords.insert("char");
1186  fgKeywords.insert("class");
1187  fgKeywords.insert("const");
1188  fgKeywords.insert("const_cast");
1189  fgKeywords.insert("continue");
1190  fgKeywords.insert("default");
1191  fgKeywords.insert("delete");
1192  fgKeywords.insert("do");
1193  fgKeywords.insert("double");
1194  fgKeywords.insert("dynamic_cast");
1195  fgKeywords.insert("else");
1196  fgKeywords.insert("enum");
1197  fgKeywords.insert("explicit");
1198  fgKeywords.insert("export");
1199  fgKeywords.insert("extern");
1200  fgKeywords.insert("false");
1201  fgKeywords.insert("float");
1202  fgKeywords.insert("for");
1203  fgKeywords.insert("friend");
1204  fgKeywords.insert("goto");
1205  fgKeywords.insert("if");
1206  fgKeywords.insert("inline");
1207  fgKeywords.insert("int");
1208  fgKeywords.insert("long");
1209  fgKeywords.insert("mutable");
1210  fgKeywords.insert("namespace");
1211  fgKeywords.insert("new");
1212  fgKeywords.insert("operator");
1213  fgKeywords.insert("private");
1214  fgKeywords.insert("protected");
1215  fgKeywords.insert("public");
1216  fgKeywords.insert("register");
1217  fgKeywords.insert("reinterpret_cast");
1218  fgKeywords.insert("return");
1219  fgKeywords.insert("short");
1220  fgKeywords.insert("signed");
1221  fgKeywords.insert("sizeof");
1222  fgKeywords.insert("static");
1223  fgKeywords.insert("static_cast");
1224  fgKeywords.insert("struct");
1225  fgKeywords.insert("switch");
1226  fgKeywords.insert("template");
1227  fgKeywords.insert("this");
1228  fgKeywords.insert("throw");
1229  fgKeywords.insert("true");
1230  fgKeywords.insert("try");
1231  fgKeywords.insert("typedef");
1232  fgKeywords.insert("typeid");
1233  fgKeywords.insert("typename");
1234  fgKeywords.insert("union");
1235  fgKeywords.insert("unsigned");
1236  fgKeywords.insert("using");
1237  fgKeywords.insert("virtual");
1238  fgKeywords.insert("void");
1239  fgKeywords.insert("volatile");
1240  fgKeywords.insert("wchar_t");
1241  fgKeywords.insert("while");
1242 }
1243 
1244 ////////////////////////////////////////////////////////////////////////////////
1245 /// return whether word at line's pos is a valid directive, and returns its
1246 /// TDocDirective's TClass object, or 0 if it's not a directive. Set begin
1247 /// to kTRUE for "Begin_..."
1248 /// You can implement your own handlers by implementing a class deriving
1249 /// from TDocHandler, and calling it TDocTagDirective for "BEGIN_TAG",
1250 /// "END_TAG" blocks.
1251 
1253  const TString& word, Bool_t& begin) const
1254 {
1255  // '"' serves as escape char
1256  if (pos > 0 && line[pos - 1] == '"')
1257  return 0;
1258 
1259  begin = word.BeginsWith("begin_", TString::kIgnoreCase);
1260  Bool_t end = word.BeginsWith("end_", TString::kIgnoreCase);
1261 
1262  if (!begin && !end)
1263  return 0;
1264 
1265  /* NO - we can have "BEGIN_HTML / * ..."
1266  if (!InContext(kComment))
1267  return 0;
1268  */
1269 
1270  TString tag = word( begin ? 6 : 4, word.Length());
1271 
1272  if (!tag.Length())
1273  return 0;
1274 
1275  tag.ToLower();
1276  tag[0] -= 'a' - 'A'; // first char is caps
1277  tag.Prepend("TDoc");
1278  tag += "Directive";
1279 
1280  TClass* clDirective = TClass::GetClass(tag, kFALSE);
1281 
1282  if (gDebug > 0 && !clDirective)
1283  Warning("IsDirective", "Unknown THtml directive %s in line %d!", word.Data(), fLineNo);
1284 
1285  return clDirective;
1286 }
1287 
1288 ////////////////////////////////////////////////////////////////////////////////
1289 /// Check if c is a valid C++ name character
1290 ///
1291 ///
1292 /// Input: c - a single character
1293 ///
1294 /// Output: TRUE if c is a valid C++ name character
1295 /// and FALSE if it's not.
1296 ///
1297 /// NOTE: Valid name characters are [a..zA..Z0..9_~],
1298 ///
1299 
1301 {
1302  Bool_t ret = kFALSE;
1303 
1304  if (isalnum(c) || c == '_' || c == '~')
1305  ret = kTRUE;
1306 
1307  return ret;
1308 }
1309 
1310 
1311 ////////////////////////////////////////////////////////////////////////////////
1312 /// Check if c is a valid first character for C++ name
1313 ///
1314 ///
1315 /// Input: c - a single character
1316 ///
1317 /// Output: TRUE if c is a valid first character for C++ name,
1318 /// and FALSE if it's not.
1319 ///
1320 /// NOTE: Valid first characters are [a..zA..Z_~]
1321 ///
1322 
1324 {
1325  Bool_t ret = kFALSE;
1326 
1327  if (isalpha(c) || c == '_' || c == '~')
1328  ret = kTRUE;
1329 
1330  return ret;
1331 }
1332 
1333 
1334 ////////////////////////////////////////////////////////////////////////////////
1335 /// Search for a method starting at posMethodName, and return its return type,
1336 /// its name, and its arguments. If the end of arguments is not found in the
1337 /// current line, get a new line from sourceFile, beautify it to srcOut, creating
1338 /// an anchor as necessary. When this function returns, posMethodName points to the
1339 /// end of the function declaration, i.e. right after the arguments' closing bracket.
1340 /// If posMethodName == kNPOS, we look for the first matching method in fMethodCounts.
1341 
1343  TString& name, TString& params,
1344  Bool_t& isconst, std::ostream &srcOut,
1345  TString &anchor, std::ifstream& sourceFile,
1346  Bool_t allowPureVirtual)
1347 {
1348  typedef std::map<std::string /*method name*/, Int_t > MethodCount_t;
1349  isconst = false;
1350 
1351  if (posMethodName == kNPOS) {
1352  name.Remove(0);
1353  TMethod * meth = 0;
1354  Ssiz_t posBlock = fLineRaw.Index('{');
1355  Ssiz_t posQuote = fLineRaw.Index('"');
1356  if (posQuote != kNPOS && (posBlock == kNPOS || posQuote < posBlock))
1357  posBlock = posQuote;
1358  if (posBlock == kNPOS)
1359  posBlock = fLineRaw.Length();
1360  for (MethodCount_t::iterator iMethodName = fMethodCounts.begin();
1361  !name.Length() && iMethodName != fMethodCounts.end(); ++iMethodName) {
1362  TString lookFor(iMethodName->first);
1363  posMethodName = fLineRaw.Index(lookFor);
1364  if (posMethodName != kNPOS && posMethodName < posBlock
1365  && (posMethodName == 0 || !IsWord(fLineRaw[posMethodName - 1]))) {
1366  // check whether the method name is followed by optional spaces and
1367  // an opening parathesis
1368  Ssiz_t posMethodEnd = posMethodName + lookFor.Length();
1369  while (isspace((UChar_t)fLineRaw[posMethodEnd])) ++posMethodEnd;
1370  if (fLineRaw[posMethodEnd] == '(') {
1371  meth = LocateMethodInCurrentLine(posMethodName, ret, name, params, isconst,
1372  srcOut, anchor, sourceFile, allowPureVirtual);
1373  if (name.Length())
1374  return meth;
1375  }
1376  }
1377  }
1378  return 0;
1379  }
1380 
1381  name = fLineRaw(posMethodName, fLineRaw.Length() - posMethodName);
1382 
1383  // extract return type
1384  ret = fLineRaw(0, posMethodName);
1385  if (ret.Length()) {
1386  while (ret.Length() && (IsName(ret[ret.Length() - 1]) || ret[ret.Length()-1] == ':'))
1387  ret.Remove(ret.Length() - 1, 1);
1388  Strip(ret);
1389  Bool_t didSomething = kTRUE;
1390  while (didSomething) {
1391  didSomething = kFALSE;
1392  if (ret.BeginsWith("inline ")) {
1393  didSomething = kTRUE;
1394  ret.Remove(0, 7);
1395  }
1396  if (ret.BeginsWith("static ")) {
1397  didSomething = kTRUE;
1398  ret.Remove(0, 7);
1399  }
1400  if (ret.BeginsWith("virtual ")) {
1401  didSomething = kTRUE;
1402  ret.Remove(0, 8);
1403  }
1404  } // while replacing static, virtual, inline
1405  Strip(ret);
1406  }
1407 
1408  // extract parameters
1409  Ssiz_t posParam = name.First('(');
1410  if (posParam == kNPOS ||
1411  // no strange return types, please
1412  ret.Contains("{") || ret.Contains("}") || ret.Contains("(") || ret.Contains(")")
1413  || ret.Contains("=")) {
1414  ret.Remove(0);
1415  name.Remove(0);
1416  params.Remove(0);
1417  return 0;
1418  }
1419 
1420  if (name.BeginsWith("operator")) {
1421  // op () (...)
1422  Ssiz_t checkOpBracketParam = posParam + 1;
1423  while (isspace((UChar_t)name[checkOpBracketParam]))
1424  ++checkOpBracketParam;
1425  if (name[checkOpBracketParam] == ')') {
1426  ++checkOpBracketParam;
1427  while (isspace((UChar_t)name[checkOpBracketParam]))
1428  ++checkOpBracketParam;
1429  if (name[checkOpBracketParam] == '(')
1430  posParam = checkOpBracketParam;
1431  }
1432  } // check for op () (...)
1433 
1434  if (posParam == kNPOS) {
1435  ret.Remove(0);
1436  name.Remove(0);
1437  params.Remove(0);
1438  return 0;
1439  }
1440 
1441  params = name(posParam, name.Length() - posParam);
1442  name.Remove(posParam);
1443  while (name.Length() && isspace((UChar_t)name[name.Length() - 1]))
1444  name.Remove(name.Length() - 1);
1445  if (!name.Length()) {
1446  ret.Remove(0);
1447  name.Remove(0);
1448  params.Remove(0);
1449  return 0;
1450  }
1451 
1452  MethodCount_t::const_iterator iMethodName = fMethodCounts.find(name.Data());
1453  if (iMethodName == fMethodCounts.end() || iMethodName->second <= 0) {
1454  ret.Remove(0);
1455  name.Remove(0);
1456  params.Remove(0);
1457  return 0;
1458  }
1459 
1460  // find end of param
1461  Ssiz_t posParamEnd = 1;
1462  Int_t bracketLevel = 1;
1463  while (bracketLevel) {
1464  const char* paramEnd = strpbrk(params.Data() + posParamEnd, ")(\"'");
1465  if (!paramEnd) {
1466  // func with params over multiple lines
1467  // gotta write out this line before it gets lost
1468  if (!anchor.Length()) {
1469  // request an anchor, just in case...
1470  AnchorFromLine(fLineStripped, anchor);
1471  if (srcOut)
1472  srcOut << "<a name=\"" << anchor << "\"></a>";
1473  }
1474  ++fLineNumber;
1475  if (srcOut)
1476  WriteSourceLine(srcOut);
1477 
1478  fLineRaw.ReadLine(sourceFile, kFALSE);
1479  if (sourceFile.eof()) {
1480  Error("LocateMethodInCurrentLine",
1481  "Cannot find end of signature for function %s!",
1482  name.Data());
1483  break;
1484  }
1485 
1487 
1488  // replace class names etc
1491 
1494 
1495  posParamEnd = params.Length();
1496  params += fLineRaw;
1497  } else
1498  posParamEnd = paramEnd - params.Data();
1499  switch (params[posParamEnd]) {
1500  case '(': ++bracketLevel; ++posParamEnd; break;
1501  case ')': --bracketLevel; ++posParamEnd; break;
1502  case '"': // skip ")"
1503  ++posParamEnd;
1504  while (params.Length() > posParamEnd && params[posParamEnd] != '"') {
1505  // skip '\"'
1506  if (params[posParamEnd] == '\\') ++posParamEnd;
1507  ++posParamEnd;
1508  }
1509  if (params.Length() <= posParamEnd) {
1510  // something is seriously wrong - skip :-/
1511  ret.Remove(0);
1512  name.Remove(0);
1513  params.Remove(0);
1514  return 0;
1515  }
1516  ++posParamEnd; // skip trailing '"'
1517  break;
1518  case '\'': // skip ')'
1519  ++posParamEnd;
1520  if (params[posParamEnd] == '\\') ++posParamEnd;
1521  posParamEnd += 2;
1522  break;
1523  default:
1524  ++posParamEnd;
1525  }
1526  } // while bracketlevel, i.e. (...(..)...)
1527 
1528  {
1529  TString pastParams(params(posParamEnd, params.Length()));
1530  pastParams = pastParams.Strip(TString::kLeading);
1531  isconst = pastParams.BeginsWith("const") && !(isalnum(pastParams[5]) || pastParams[5] == '_');
1532  }
1533 
1534  Ssiz_t posBlock = params.Index('{', posParamEnd);
1535  Ssiz_t posSemicolon = params.Index(';', posParamEnd);
1536  Ssiz_t posPureVirt = params.Index('=', posParamEnd);
1537  if (posSemicolon != kNPOS)
1538  if ((posBlock == kNPOS || (posSemicolon < posBlock)) &&
1539  (posPureVirt == kNPOS || !allowPureVirtual)
1540  && !allowPureVirtual) // allow any "func();" if pv is allowed
1541  params.Remove(0);
1542 
1543  if (params.Length())
1544  params.Remove(posParamEnd);
1545 
1546  if (!params.Length()) {
1547  ret.Remove(0);
1548  name.Remove(0);
1549  return 0;
1550  }
1551  // update posMethodName to point behind the method
1552  posMethodName = posParam + posParamEnd;
1553  if (fCurrentClass) {
1555  if (meth) {
1556  fDirectiveCount = 0;
1557  fCurrentMethodTag = name + "_";
1559  return meth;
1560  }
1561  }
1562 
1563  return 0;
1564 }
1565 
1566 
1567 ////////////////////////////////////////////////////////////////////////////////
1568 /// Locate methods, starting in the source file, then inline, then
1569 /// immediately inside the class declaration. While doing that also
1570 /// find the class description and special tags like the macro tag etc.
1571 
1572 void TDocParser::Parse(std::ostream& out)
1573 {
1575 
1577 
1578  LocateMethodsInSource(out);
1581 
1582  if (!fSourceInfo[kInfoLastUpdate].Length()) {
1583  TDatime date;
1585  }
1586 }
1587 
1588 ////////////////////////////////////////////////////////////////////////////////
1589 /// Collect methods from the source or header file called filename.
1590 /// It generates a beautified version of the source file on the fly;
1591 /// the output file is given by the fCurrentClass's name, and sourceExt.
1592 /// Documentation is extracted to out.
1593 /// lookForSourceInfo: if set, author, lastUpdate, and copyright are
1594 /// extracted (i.e. the values contained in fSourceInfo)
1595 /// useDocxxStyle: if set, documentation can be in front of the method
1596 /// name, not only inside the method. Useful doc Doc++/Doxygen style,
1597 /// and inline methods.
1598 /// lookForClassDescr: if set, the first line matching the class description
1599 /// rules is assumed to be the class description for fCurrentClass; the
1600 /// description is written to out.
1601 /// methodPattern: if set, methods have to be prepended by this tag. Usually
1602 /// the class name + "::". In header files, looking for in-place function
1603 /// definitions, this should be 0. In that case, only functions in
1604 /// fMethodCounts are searched for.
1605 
1606 void TDocParser::LocateMethods(std::ostream& out, const char* filename,
1607  Bool_t lookForSourceInfo /*= kTRUE*/,
1608  Bool_t useDocxxStyle /*= kFALSE*/,
1609  Bool_t allowPureVirtual /*= kFALSE*/,
1610  const char* methodPattern /*= 0*/,
1611  const char* sourceExt /*= 0 */)
1612 {
1613  TString sourceFileName(filename);
1614  fCurrentFile = filename;
1615  if (!sourceFileName.Length()) {
1616  fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
1617  Error("LocateMethods", "Can't find source file '%s' for class %s!",
1618  sourceFileName.Data(), fCurrentClass->GetName());
1619  return;
1620  }
1621  std::ifstream sourceFile(sourceFileName.Data());
1622  if (!sourceFile || !sourceFile.good()) {
1623  Error("LocateMethods", "Can't open file '%s' for reading!", sourceFileName.Data());
1624  return;
1625  }
1626 
1627  TPMERegexp patternRE(methodPattern ? methodPattern : "");
1628 
1629  TString codeOneLiner;
1630  TString methodRet;
1631  TString methodName;
1632  TString methodParam;
1633  Bool_t methodIsConst = kFALSE;
1634  TString anchor;
1635  TString docxxComment;
1636 
1637  Bool_t wroteMethodNowWaitingForOpenBlock = kFALSE;
1638 
1639  std::ofstream srcHtmlOut;
1640  TString srcHtmlOutName;
1641  if (sourceExt && sourceExt[0]) {
1642  static_cast<TClassDocOutput*>(fDocOutput)->CreateSourceOutputStream(srcHtmlOut, sourceExt, srcHtmlOutName);
1643  fLineNumber = 0;
1644  } else {
1645  sourceExt = 0;
1646  srcHtmlOutName = fCurrentClass->GetName();
1647  fDocOutput->NameSpace2FileName(srcHtmlOutName);
1648  gSystem->PrependPathName("src", srcHtmlOutName);
1649  srcHtmlOutName += ".h.html";
1650  }
1651 
1652  fParseContext.clear();
1653  fParseContext.push_back(kCode);
1654  fDocContext = kIgnore;
1655  fLineNo = 0;
1656 
1657  while (!sourceFile.eof()) {
1658  Bool_t needAnchor = kFALSE;
1659 
1660  ++fLineNo; // we count fortrany
1661 
1662  fLineRaw.ReadLine(sourceFile, kFALSE);
1663  if (sourceFile.eof()) break;
1664 
1666 
1667  // replace class names etc
1670 
1672  fLineComment = "";
1674 
1675  if (!ProcessComment()) {
1676  // not a commented line
1677 
1679  TString strippedComment(fComment);
1680  Strip(strippedComment);
1681  if (strippedComment.Length() > 0) {
1686  }
1687  }
1688  fDocContext = kIgnore;
1689  }
1690 
1691  Ssiz_t impIdx = fLineStripped.Index("ClassImp(");
1692  if (impIdx == 0 && fClassDocState == kClassDoc_LookingHaveSomething) {
1694  // take unscoped version
1695  Ssiz_t posLastScope = kNPOS;
1696  while ((posLastScope = name.Index("::")) != kNPOS)
1697  name.Remove(0, posLastScope + 2);
1698 
1699  Ssiz_t posName = fLineStripped.Index(name, impIdx);
1700  if (posName != kNPOS) {
1701  Ssiz_t posClosingParen = posName + name.Length();
1702  while (isspace(fLineStripped[posClosingParen])) ++posClosingParen;
1703  if (fLineStripped[posClosingParen] == ')') {
1704  WriteClassDoc(out, kFALSE);
1705  fDocContext = kIgnore;
1706  }
1707  }
1708  }
1709 
1710  if (fLineStripped.Length())
1711  // remove last class doc if it not followed by ClassImp
1712  // (with optional empty lines in between)
1713  fLastClassDoc = "";
1714 
1715  // write previous method
1716  if (methodName.Length() && !wroteMethodNowWaitingForOpenBlock) {
1717  TString savedComment;
1718  if (useDocxxStyle && docxxComment.Length()) {
1719  savedComment = fComment;
1720  fComment = docxxComment;
1721  }
1722  WriteMethod(out, methodRet, methodName, methodParam, methodIsConst,
1723  gSystem->BaseName(srcHtmlOutName), anchor, codeOneLiner);
1724  docxxComment.Remove(0);
1725  if (savedComment[0]) {
1726  fComment = savedComment;
1727  }
1728  }
1729 
1730  if (!wroteMethodNowWaitingForOpenBlock) {
1731  // check for method
1732  Ssiz_t posPattern = kNPOS;
1733  if (methodPattern) {
1734  posPattern = fLineRaw.Index((TPRegexp&)patternRE);
1735  }
1736  if (posPattern != kNPOS && methodPattern) {
1737  // no strings, no blocks in front of function declarations / implementations
1738  static const char vetoChars[] = "{\"";
1739  for (int ich = 0; posPattern != kNPOS && vetoChars[ich]; ++ich) {
1740  Ssiz_t posVeto = fLineRaw.Index(vetoChars[ich]);
1741  if (posVeto != kNPOS && posVeto < posPattern)
1742  posPattern = kNPOS;
1743  }
1744  }
1745  if (posPattern != kNPOS || !methodPattern) {
1746  if (methodPattern) {
1747  patternRE.Match(fLineRaw);
1748  posPattern += patternRE[0].Length();
1749  }
1750  LocateMethodInCurrentLine(posPattern, methodRet, methodName,
1751  methodParam, methodIsConst, srcHtmlOut,
1752  anchor, sourceFile, allowPureVirtual);
1753  if (methodName.Length()) {
1755  needAnchor = !anchor.Length();
1756  if (useDocxxStyle)
1757  docxxComment = fComment;
1758  fComment.Remove(0);
1759  codeOneLiner.Remove(0);
1760 
1761  wroteMethodNowWaitingForOpenBlock = fLineRaw.Index("{", posPattern) == kNPOS;
1762  wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(";", posPattern) == kNPOS;
1763  } else if (fLineRaw.First("{};") != kNPOS)
1764  // these chars reset the preceding comment
1765  fComment.Remove(0);
1766  } // pattern matches - could be a method
1767  else
1768  fComment.Remove(0);
1769  } else {
1770  wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index("{") == kNPOS;
1771  wroteMethodNowWaitingForOpenBlock &= fLineRaw.Index(";") == kNPOS;
1772  } // if !wroteMethodNowWaitingForOpenBlock
1773 
1774  if (methodName.Length() && !wroteMethodNowWaitingForOpenBlock) {
1775  // make sure we don't have more '{' in commentLine than in fLineRaw
1776  if (!codeOneLiner.Length() &&
1777  fLineSource.CountChar('{') == 1 &&
1778  fLineSource.CountChar('}') == 1) {
1779  // a one-liner
1780  codeOneLiner = fLineSource;
1781  codeOneLiner.Remove(0, codeOneLiner.Index('{'));
1782  codeOneLiner.Remove(codeOneLiner.Index('}') + 1);
1783  }
1784  } // if method name and '{'
1785  // else not a comment, and we don't need the previous one:
1786  else if (!methodName.Length() && !useDocxxStyle)
1787  fComment.Remove(0);
1788 
1789  if (needAnchor || fExtraLinesWithAnchor.find(fLineNo) != fExtraLinesWithAnchor.end()) {
1790  AnchorFromLine(fLineStripped, anchor);
1791  if (sourceExt)
1792  srcHtmlOut << "<a name=\"" << anchor << "\"></a>";
1793  }
1794  // else anchor.Remove(0); - NO! WriteMethod will need it later!
1795  } // if !comment
1796 
1797  // check for last update,...
1798  Ssiz_t posTag = kNPOS;
1799  if (lookForSourceInfo)
1800  for (Int_t si = 0; si < (Int_t) kNumSourceInfos; ++si)
1801  if (!fSourceInfo[si].Length() && (posTag = fLineRaw.Index(fSourceInfoTags[si])) != kNPOS) {
1802  fSourceInfo[si] = fLineRaw(posTag + strlen(fSourceInfoTags[si]), fLineRaw.Length() - posTag);
1803  if (si == kInfoAuthor)
1805  }
1806 
1807 
1808  // write to .cxx.html
1809  ++fLineNumber;
1810  if (srcHtmlOut)
1811  WriteSourceLine(srcHtmlOut);
1812  else if (needAnchor)
1814  } // while !sourceFile.eof()
1815 
1816  // deal with last func
1817  if (methodName.Length()) {
1818  if (useDocxxStyle && docxxComment.Length())
1819  fComment = docxxComment;
1820  WriteMethod(out, methodRet, methodName, methodParam, methodIsConst,
1821  gSystem->BaseName(srcHtmlOutName), anchor, codeOneLiner);
1822  docxxComment.Remove(0);
1823  } else
1824  WriteClassDoc(out);
1825 
1826  srcHtmlOut << "</pre>" << std::endl;
1827 
1829 
1830  srcHtmlOut << "</div>" << std::endl;
1831 
1832  fDocOutput->WriteHtmlFooter(srcHtmlOut, "../");
1833 
1834  fParseContext.clear();
1835  fParseContext.push_back(kCode);
1836  fDocContext = kIgnore;
1837  fCurrentFile = "";
1838 }
1839 
1840 ////////////////////////////////////////////////////////////////////////////////
1841 /// Given fCurrentClass, look for methods in its source file,
1842 /// and extract documentation to out, while beautifying the source
1843 /// file in parallel.
1844 
1845 void TDocParser::LocateMethodsInSource(std::ostream& out)
1846 {
1847  // for Doc++ style
1848  Bool_t useDocxxStyle = (fHtml->GetDocStyle() == "Doc++");
1849 
1851  // take unscoped version
1852  Ssiz_t posLastScope = kNPOS;
1853  while ((posLastScope = pattern.Index("::")) != kNPOS)
1854  pattern.Remove(0, posLastScope + 2);
1855  pattern += "::";
1856 
1857  TString implFileName;
1858  if (fHtml->GetImplFileName(fCurrentClass, kTRUE, implFileName)) {
1859  LocateMethods(out, implFileName, kFALSE /*source info*/, useDocxxStyle,
1860  kFALSE /*allowPureVirtual*/, pattern, ".cxx.html");
1861  Ssiz_t posGt = pattern.Index('>');
1862  if (posGt != kNPOS) {
1863  // template! Re-run with pattern '...<.*>::'
1864  Ssiz_t posLt = pattern.Index('<');
1865  if (posLt != kNPOS && posLt < posGt) {
1866  pattern.Replace(posLt + 1, posGt - posLt - 1, ".*");
1867  LocateMethods(out, implFileName, kFALSE /*source info*/, useDocxxStyle,
1868  kFALSE /*allowPureVirtual*/, pattern, ".cxx.html");
1869  }
1870  }
1871  }
1872 }
1873 
1874 ////////////////////////////////////////////////////////////////////////////////
1875 /// Given fCurrentClass, look for methods in its header file,
1876 /// and extract documentation to out.
1877 
1879 {
1880  // for inline methods, always allow doc before func
1881  Bool_t useDocxxStyle = kTRUE;
1882 
1884  // take unscoped version
1885  Ssiz_t posLastScope = kNPOS;
1886  while ((posLastScope = pattern.Index("::")) != kNPOS)
1887  pattern.Remove(0, posLastScope + 1);
1888  pattern += "::";
1889 
1890  TString declFileName;
1891  if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declFileName)) {
1892  LocateMethods(out, declFileName, kTRUE /*source info*/, useDocxxStyle,
1893  kFALSE /*allowPureVirtual*/, pattern, 0);
1894  Ssiz_t posGt = pattern.Index('>');
1895  if (posGt != kNPOS) {
1896  // template! Re-run with pattern '...<.*>::'
1897  Ssiz_t posLt = pattern.Index('<');
1898  if (posLt != kNPOS && posLt < posGt) {
1899  pattern.Replace(posLt + 1, posGt - posLt - 1, ".*");
1900  LocateMethods(out, declFileName, kTRUE /*source info*/, useDocxxStyle,
1901  kFALSE /*allowPureVirtual*/, pattern, 0);
1902  }
1903  }
1904  }
1905 }
1906 
1907 ////////////////////////////////////////////////////////////////////////////////
1908 /// Given fCurrentClass, look for methods in its header file's
1909 /// class declaration block, and extract documentation to out,
1910 /// while beautifying the header file in parallel.
1911 
1913 {
1914  TString declFileName;
1915  if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declFileName))
1916  LocateMethods(out, declFileName, kTRUE/*source info*/, kTRUE /*useDocxxStyle*/,
1917  kTRUE /*allowPureVirtual*/, 0, ".h.html");
1918 }
1919 
1920 ////////////////////////////////////////////////////////////////////////////////
1921 /// Parse the current line as a comment, handling directives and re-formatting
1922 /// the comment: remove "/*", "*/", "//", similar characters surrounding lines,
1923 /// etc.
1924 ///
1925 /// Return kFALSE if the line is not a comment.
1926 
1928 {
1929  if (!fCommentAtBOL
1930  && !(fLineStripped[0] == '/'
1931  && (fLineStripped[1] == '/' || fLineStripped[1] == '*'))
1932  && !InContext(kComment) && !InContext(kDirective)) {
1933  fLineComment = "";
1934  return kFALSE;
1935  }
1936 
1937  //if (InContext(kDirective))
1938  // return kTRUE; - NO! we might have a comment from a previous directive!
1939 
1940  // don't write out empty lines if the current directive is eating the line
1942  return kTRUE;
1943 
1944  TString commentLine(fLineComment.Strip());
1945 
1946  // remove all <span class="comment"> tags
1947  Bool_t mustDealWithCommentAtBOL = fCommentAtBOL; // whether we had a closing "*/"
1948  Ssiz_t posComment = kNPOS;
1949  if (!fCommentAtBOL)
1950  posComment = commentLine.Index("<span class=\"comment\">", 0, TString::kIgnoreCase);
1951  Ssiz_t posSpanEnd = commentLine.Index("</span>", posComment == kNPOS?0:posComment, TString::kIgnoreCase);
1952  while ((mustDealWithCommentAtBOL && posSpanEnd != kNPOS) || posComment != kNPOS) {
1953  Int_t spanLevel = 1;
1954  Ssiz_t posSpan = commentLine.Index("<span", posComment + 1, TString::kIgnoreCase);
1955  while (spanLevel > 1 || (posSpan != kNPOS && posSpan < posSpanEnd)) {
1956  // another span was opened, take the next </span>
1957  if (posSpan != kNPOS && posSpan < posSpanEnd) {
1958  ++spanLevel;
1959  posSpan = commentLine.Index("<span", posSpan + 1, TString::kIgnoreCase);
1960  // posSpanEnd doesn't change
1961  continue;
1962  } // else
1963  --spanLevel;
1964  // posSpan doesn't change
1965  posSpanEnd = commentLine.Index("</span>", posSpanEnd + 1, TString::kIgnoreCase);
1966  }
1967  if (posSpanEnd != kNPOS) {
1968  // only remove span if </span> if it exists (or we end up with unbalanced spans)
1969  commentLine.Remove(posSpanEnd, 7);
1970  if (posComment != kNPOS)
1971  commentLine.Remove(posComment, 22);
1972  else {
1973  mustDealWithCommentAtBOL = kFALSE;
1974  // now remove C comments
1975  posComment = 0;
1976  }
1977  posComment = commentLine.Index("<span class=\"comment\">", posComment, TString::kIgnoreCase);
1978  } else break;
1979  }
1980  if (posComment != kNPOS)
1981  commentLine.Remove(posComment, 22);
1982 
1983  // don't strip in C comments, do strip if opening:
1985  || (fLineStripped[0] == '/' && fLineStripped[1] == '*'))
1986  Strip(commentLine);
1987 
1988  // look for start tag of class description
1991  && !fComment.Length()
1992  && fDocContext == kIgnore && commentLine.Contains(fClassDescrTag)) {
1994  }
1995 
1996  char start_or_end = 0;
1997  // remove leading /*, //
1998  if (commentLine.Length()>1 && commentLine[0] == '/'
1999  && (commentLine[1] == '/' || commentLine[1] == '*')) {
2000  start_or_end = commentLine[1];
2001  commentLine.Remove(0, 2);
2002  }
2003  // remove trailing */
2004  if (start_or_end != '/' && commentLine.Length()>1
2005  && commentLine[commentLine.Length() - 2] == '*'
2006  && commentLine[commentLine.Length() - 1] == '/') {
2007  start_or_end = commentLine[commentLine.Length() - 2];
2008  commentLine.Remove(commentLine.Length()-2);
2009  }
2010 
2011  // remove repeating characters from the end of the line
2012  if (start_or_end && commentLine.Length() > 3) {
2013  TString lineAllOneChar(commentLine.Strip());
2014 
2015  Ssiz_t len = lineAllOneChar.Length();
2016  if (len > 2) {
2017  Char_t c = lineAllOneChar[len - 1];
2018  if (c == lineAllOneChar[len - 2] && c == lineAllOneChar[len - 3]) {
2019  TString lineAllOneCharStripped = lineAllOneChar.Strip(TString::kTrailing, c);
2020  Strip(lineAllOneCharStripped);
2021  if (!lineAllOneCharStripped.Length()) {
2022  commentLine.Remove(0);
2023 
2024  // also a class doc signature: line consists of ////
2027  && !fComment.Length()
2028  && fDocContext == kIgnore && start_or_end=='/') {
2030  }
2031  }
2032  }
2033  }
2034  }
2035 
2036  // remove leading and trailing chars from e.g. // some doc //
2037  if (commentLine.Length() > 0 && start_or_end == commentLine[commentLine.Length() - 1])
2038  // we already removed it as part of // or / *; also remove the trailing
2039  commentLine = commentLine.Strip(TString::kTrailing, start_or_end);
2040 
2041  if (commentLine.Length() > 2 && Context() != kDirective)
2042  while (commentLine.Length() > 2
2043  && !IsWord(commentLine[0])
2044  && commentLine[0] == commentLine[commentLine.Length() - 1])
2045  commentLine = commentLine.Strip(TString::kBoth, commentLine[0]);
2046 
2047  // remove leading '/' if we had // or '*' if we had / *
2048  while (start_or_end && commentLine[0] == start_or_end)
2049  commentLine.Remove(0, 1);
2050 
2051  fComment += commentLine + "\n";
2052 
2053  return kTRUE;
2054 }
2055 
2056 ////////////////////////////////////////////////////////////////////////////////
2057 /// remove the top-most comment context that matches cxxcomment,
2058 
2060 {
2061  UInt_t lookFor = kComment;
2062  if (cxxcomment) lookFor |= kCXXComment;
2063  std::list<UInt_t>::iterator iComment = fParseContext.end();
2064  for (std::list<UInt_t>::iterator iContext = fParseContext.begin();
2065  iContext != fParseContext.end(); ++ iContext)
2066  if (*iContext == lookFor) iComment =iContext;
2067  if (iComment != fParseContext.end())
2068  fParseContext.erase(iComment);
2069 }
2070 
2071 ////////////////////////////////////////////////////////////////////////////////
2072 /// strips ' ', tabs, and newlines from both sides of str
2073 
2075 {
2076  Bool_t changed = str[0] == ' ' || str[0] == '\t' || str[0] == '\n';
2077  changed |= str.Length()
2078  && (str[str.Length() - 1] == ' ' || str[str.Length() - 1] == '\t'
2079  || str[str.Length() - 1] == '\n');
2080  if (!changed) return kFALSE;
2081  Ssiz_t i = 0;
2082  while (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')
2083  ++i;
2084  str.Remove(0,i);
2085  i = str.Length() - 1;
2086  while (i >= 0 && (str[i] == ' ' || str[i] == '\t' || str[i] == '\n'))
2087  --i;
2088  str.Remove(i + 1, str.Length());
2089  return kTRUE;
2090 }
2091 
2092 ////////////////////////////////////////////////////////////////////////////////
2093 /// Write the class description depending (among others) on fClassDocState.
2094 
2095 void TDocParser::WriteClassDoc(std::ostream& out, Bool_t first /*= kTRUE*/)
2096 {
2099  static_cast<TClassDocOutput*>(fDocOutput)->WriteClassDescription(out, classDoc);
2101  }
2102 
2103 }
2104 
2105 namespace {
2106  static void RemoveUnneededSpaces(TString& s) {
2107  // Remove spaces except between identifier characters.
2108  // Assumes s is stripped (does not start nor end with space).
2109  for (Ssiz_t i = 1; i < s.Length() - 1; ++i) {
2110  if (s[i] == ' ') {
2111  char p = s[i - 1];
2112  char n = s[i + 1];
2113  if (((isalnum(p) || p == '_') && (isalnum(n) || n == '_'))
2114  || (p == '>' && n == '>')) {
2115  // "id id" or "> >": keep space
2116  } else {
2117  while (isspace(s[i])) {
2118  s.Remove(i, 1);
2119  }
2120  }
2121  }
2122  }
2123  }
2124 
2125  static void ParseParameters(TString& strippedParams, TList& paramArr) {
2126  // Extract a list of strings (the parameters without initializers) from
2127  // the signature.
2128  int nest = 0;
2129  bool init = false;
2130  bool quoted = false;
2131  Ssiz_t len = strippedParams.Length();
2132  TString arg;
2133  for (Ssiz_t i = 0; i < len; ++i) {
2134  switch (strippedParams[i]) {
2135  case '<': // fallthrough
2136  case '(': // fallthrough
2137  case '[': ++nest; break;
2138  case '>': // fallthrough
2139  case ')': // fallthrough
2140  case ']': --nest; break;
2141  case '=': init = true; break;
2142  case '\'': ++i; if (strippedParams[i] == '\\') ++i; ++i; continue;
2143  case '\\': ++i; continue; break;
2144  case '"': quoted = !quoted; break;
2145  case ',': {
2146  if (!quoted && !nest) {
2147  TString strippedArg(arg.Strip(TString::kBoth));
2148  paramArr.AddLast(new TObjString(strippedArg));
2149  init = false;
2150  arg.Remove(0);
2151  continue;
2152  }
2153  }
2154  }
2155  if (!init) {
2156  arg += strippedParams[i];
2157  }
2158  }
2159  TString strippedLastArg(arg.Strip(TString::kBoth));
2160  if (strippedLastArg.Length()) {
2161  paramArr.AddLast(new TObjString(strippedLastArg));
2162  }
2163  }
2164 
2165  void MatchOverloadSignatures(TCollection* candidates, TList* paramArr)
2166  {
2167  // Check type identity of candidate signatures. For each argument, check whether it
2168  // reduces the list of candidates to > 0 elements.
2169  TList suppressed;
2170  TIter iCandidate(candidates);
2171  int nparams = paramArr->GetSize();
2172  for (int iparam = 0; iparam < nparams && candidates->GetSize() > 1; ++iparam) {
2173  TString& srcArg = ((TObjString*)paramArr->At(iparam))->String();
2174  TString noParName(srcArg);
2175  while (noParName.Length()
2176  && (isalnum(noParName[noParName.Length() - 1]) || noParName[noParName.Length() - 1] == '_'))
2177  noParName.Remove(noParName.Length() - 1);
2178  noParName = noParName.Strip(TString::kTrailing);
2179 
2180  if (noParName.Length()) {
2181  RemoveUnneededSpaces(noParName);
2182  }
2183  RemoveUnneededSpaces(srcArg);
2184  // comparison:
2185  // 0: strcmp
2186  // 1: source's parameter has last identifier (parameter name?) removed
2187  // 2: candidate type name contained in source parameter
2188  for (int comparison = 0; comparison < 5; ++comparison) {
2189  if (comparison == 1 && noParName == srcArg)
2190  // there is no parameter name to ignore
2191  continue;
2192  suppressed.Clear();
2193  iCandidate.Reset();
2194  TDocMethodWrapper* method = 0;
2195  while ((method = (TDocMethodWrapper*) iCandidate())) {
2196  TMethodArg* methArg = (TMethodArg*) method->GetMethod()->GetListOfMethodArgs()->At(iparam);
2197  TString sMethArg = methArg->GetFullTypeName();
2198  RemoveUnneededSpaces(sMethArg);
2199  bool matches = false;
2200  switch (comparison) {
2201  case 0: matches = (srcArg == sMethArg); break;
2202  case 1: matches = (noParName == sMethArg); break;
2203  case 2: matches = srcArg.Contains(sMethArg) || sMethArg.Contains(srcArg); break;
2204  }
2205  if (!matches) {
2206  suppressed.Add(method);
2207  }
2208  }
2209  if (suppressed.GetSize()
2210  && suppressed.GetSize() < candidates->GetSize()) {
2211  candidates->RemoveAll(&suppressed);
2212  break;
2213  }
2214  if (!suppressed.GetSize()) {
2215  // we have a match, no point in trying a looser matching
2216  break;
2217  }
2218  }
2219  }
2220  if (candidates->GetSize() > 1) {
2221  // use TDocMethodWrapper::kDocumented bit
2222  suppressed.Clear();
2223  iCandidate.Reset();
2224  TDocMethodWrapper* method = 0;
2225  while ((method = (TDocMethodWrapper*) iCandidate())) {
2226  if (method->TestBit(TDocMethodWrapper::kDocumented)) {
2227  suppressed.AddLast(method);
2228  }
2229  }
2230  if (suppressed.GetSize()
2231  && suppressed.GetSize() < candidates->GetSize()) {
2232  candidates->RemoveAll(&suppressed);
2233  }
2234  }
2235  }
2236 }
2237 
2238 ////////////////////////////////////////////////////////////////////////////////
2239 /// Write a method, forwarding to TClassDocOutput
2240 
2241 void TDocParser::WriteMethod(std::ostream& out, TString& ret,
2242  TString& name, TString& params, Bool_t isconst,
2243  const char* filename, TString& anchor,
2244  TString& codeOneLiner)
2245 {
2246  // if we haven't found the class description until now it's too late.
2248  WriteClassDoc(out);
2249 
2250  TString strippedParams(params);
2251  if (strippedParams[0] == '(') {
2252  strippedParams.Remove(0, 1);
2253  strippedParams.Remove(strippedParams.Length() - 1);
2254  strippedParams = strippedParams.Strip(TString::kBoth);
2255  }
2256 
2257  TList paramArr;
2258  paramArr.SetOwner();
2259  ParseParameters(strippedParams, paramArr);
2260  int nparams = paramArr.GetSize();
2261 
2262  // Collect overload candidates
2263  TList candidates;
2264  for (int access = 0; access < 3; ++access) {
2265  const TList* methList = fMethods[access].GetListForObject(name);
2266  if (!methList) continue;
2267 
2268  TIter nextMethod(methList);
2269  TDocMethodWrapper* method = 0;
2270  while ((method = (TDocMethodWrapper *) nextMethod())) {
2271  if (name == method->GetName()
2272  && isconst == ((method->GetMethod()->Property() & kIsConstMethod) > 0)
2273  && method->GetMethod()->GetListOfMethodArgs()->GetSize() == nparams) {
2274  candidates.Add(method);
2275  }
2276  }
2277  }
2278 
2279  if (nparams && candidates.GetSize() > 1) {
2280  MatchOverloadSignatures(&candidates, &paramArr);
2281  }
2282 
2283  TDocMethodWrapper* guessedMethod = 0;
2284  if (candidates.GetSize() == 1) {
2285  guessedMethod = (TDocMethodWrapper*) candidates.First();
2286  guessedMethod->SetBit(TDocMethodWrapper::kDocumented);
2287  }
2288 
2289  static_cast<TClassDocOutput*>(fDocOutput)->WriteMethod(out, ret, name, params, filename, anchor,
2290  fComment, codeOneLiner, guessedMethod);
2291 
2293  ret.Remove(0);
2294  name.Remove(0);
2295  params.Remove(0);
2296  anchor.Remove(0);
2297  fComment.Remove(0);
2298 
2299  fDocContext = kIgnore;
2300 }
2301 
2302 ////////////////////////////////////////////////////////////////////////////////
2303 /// Write fLineSource to out.
2304 /// Adjust relative paths first.
2305 
2306 void TDocParser::WriteSourceLine(std::ostream& out)
2307 {
2309  out << fLineSource << std::endl;
2310 
2311 }
A zero length substring is legal.
Definition: TString.h:77
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:926
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TDocParser(TClassDocOutput &docOutput, TClass *cl)
Constructor called for parsing class sources.
Definition: TDocParser.cxx:149
THtml * fHtml
Definition: TDocParser.h:86
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3536
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:861
void WriteLineNumbers(std::ostream &out, Long_t nLines, const TString &infileBase) const
Create a div containing the line numbers (for a source listing) 1 to nLines.
virtual bool GetImplFileName(TClass *cl, Bool_t filesys, TString &out_name) const
Return implementation file name.
Definition: THtml.cxx:2105
virtual ULong_t Hash() const
Return hash value for this object.
Definition: TObject.cxx:432
auto * m
Definition: textangle.C:8
TLine * line
Collectable string class.
Definition: TObjString.h:28
TMethod * LocateMethodInCurrentLine(Ssiz_t &posMethodName, TString &ret, TString &name, TString &params, Bool_t &isconst, std::ostream &srcOut, TString &anchor, std::ifstream &sourcefile, Bool_t allowPureVirtual)
Search for a method starting at posMethodName, and return its return type, its name, and its arguments.
const char * GetReturnTypeName() const
Get full type description of function return type, e,g.: "class TDirectory*".
Definition: TFunction.cxx:140
enum TDocParser::@89 fClassDocState
virtual void DeleteDirectiveOutput() const
Delete output generated by prior runs of all known directives; the output file names might have chang...
Definition: TDocParser.cxx:883
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Definition: TBaseClass.cxx:63
std::istream & ReadLine(std::istream &str, Bool_t skipWhite=kTRUE)
Read a line from stream upto newline skipping any whitespace.
Definition: Stringio.cxx:65
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
void SetTag(const char *tag)
Definition: TDocDirective.h:58
UInt_t fLineNo
Definition: TDocParser.h:88
virtual Bool_t GetResult(TString &result)=0
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual TObject * Last() const
Return the last object in the list. Returns 0 when list is empty.
Definition: TList.cxx:690
TString fSourceInfoTags[kNumSourceInfos]
Definition: TDocParser.h:117
TString fComment
Definition: TDocParser.h:93
void AddClassDataMembersRecursively(TBaseClass *bc)
Add data members of fCurrentClass and of bc to datamembers, recursively.
Definition: TDocParser.cxx:305
const TString & GetLastUpdateTag() const
Definition: THtml.h:306
#define gROOT
Definition: TROOT.h:415
UInt_t InContext(Int_t context) const
checks whether we are in a parse context, return the entry closest to the current context...
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3646
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
Basic string class.
Definition: TString.h:131
void DecrementMethodCount(const char *name)
reduce method count for method called name, removing it from fMethodCounts once the count reaches 0...
Definition: TDocParser.cxx:868
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Ssiz_t Length() const
Definition: TString.h:114
Bool_t CopyHtmlFile(const char *sourceName, const char *destName="")
Copy file to HTML directory.
Definition: TDocOutput.cxx:591
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition: TMethodArg.h:31
void GetCurrentModule(TString &out_module) const
Return the name of module for which sources are currently parsed.
Definition: TDocParser.cxx:966
const TString & GetDocStyle() const
Definition: THtml.h:316
TString & Prepend(const char *cs)
Definition: TString.h:656
const char * GetFullTypeName() const
Get full type description of method argument, e.g.: "class TDirectory*".
Definition: TMethodArg.cxx:75
THashList fMethods[3]
Definition: TDocParser.h:122
void WriteClassDoc(std::ostream &out, Bool_t first=kTRUE)
Write the class description depending (among others) on fClassDocState.
virtual Int_t GetOverloadIdx() const =0
Long_t fLineNumber
Definition: TDocParser.h:101
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4270
virtual void DecorateEntityBegin(TString &str, Ssiz_t &pos, TDocParser::EParseContext type)
Add some colors etc to a source entity, contained in str.
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition: TList.cxx:149
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:693
const TString & GetClassDocTag() const
Definition: THtml.h:304
virtual void Sort(Bool_t order=kSortAscending)
Sort linked list.
Definition: TList.cxx:934
virtual void DecorateEntityEnd(TString &str, Ssiz_t &pos, TDocParser::EParseContext type)
Add some colors etc to a source entity, contained in str.
const char * String
Definition: TXMLSetup.cxx:93
void RemoveCommentContext(Bool_t cxxcomment)
remove the top-most comment context that matches cxxcomment,
TString fLastClassDoc
Definition: TDocParser.h:95
virtual Bool_t ProcessComment()
void Class()
Definition: Class.C:29
virtual void ExpandCPPLine(TString &line, Ssiz_t &pos)
Expand preprocessor statements.
Definition: TDocParser.cxx:910
void WriteSourceLine(std::ostream &out)
Write fLineSource to out.
void SetCounter(Int_t count)
Definition: TDocDirective.h:59
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
void Convert(std::ostream &out, std::istream &in, const char *relpath, Bool_t isCode, Bool_t interpretDirectives)
Parse text file "in", add links etc, and write output to "out".
Definition: TDocParser.cxx:401
virtual ~TDocParser()
destructor, checking whether all methods have been found for gDebug > 3
Definition: TDocParser.cxx:210
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1072
static Bool_t Strip(TString &s)
strips &#39; &#39;, tabs, and newlines from both sides of str
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TFunction.cxx:183
static const std::string pattern("pattern")
virtual bool GetFileNameFromInclude(const char *included, TString &out_fsname) const
Set out_fsname to the full pathname corresponding to a file included as "included".
Definition: THtml.cxx:620
TList fDataMembers[6]
Definition: TDocParser.h:123
TDataType * GetDataType() const
Definition: TDataMember.h:74
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:499
static constexpr double s
void WriteHtmlFooter(std::ostream &out, const char *dir, const char *lastUpdate, const char *author, const char *copyright, const char *footer)
Write HTML footer.
TList fDirectiveHandlers
Definition: TDocParser.h:118
const TList * GetListForObject(const char *name) const
Return the THashTable&#39;s list (bucket) in which obj can be found based on its hash; see THashTable::Ge...
Definition: THashList.cxx:283
virtual void GetModuleNameForClass(TString &module, TClass *cl) const
Return the module name for a given class.
Definition: THtml.cxx:1532
TDocOutput * fDocOutput
Definition: TDocParser.h:87
void SetParser(TDocParser *parser)
Set the parser, and fDocOutput, fHtml from that.
TString fClassDescrTag
Definition: TDocParser.h:116
virtual void Parse(std::ostream &out)
Locate methods, starting in the source file, then inline, then immediately inside the class declarati...
static Bool_t IsWord(UChar_t c)
Check if c is a valid first character for C++ name.
A doubly linked list.
Definition: TList.h:44
virtual TClass * IsDirective(const TString &line, Ssiz_t pos, const TString &word, Bool_t &begin) const
return whether word at line&#39;s pos is a valid directive, and returns its TDocDirective&#39;s TClass object...
virtual void AdjustSourcePath(TString &line, const char *relpath="../")
adjust the path of links for source files, which are in src/, but need to point to relpath (usually "...
Definition: TDocOutput.cxx:295
Int_t GetType() const
Definition: TDataType.h:68
const TString & GetAuthorTag() const
Definition: THtml.h:305
TClass * fCurrentClass
Definition: TDocParser.h:96
virtual TList * GetListOfMethodArgs()
Returns methodarg list and additionally updates fDataMember in TMethod by calling FindDataMember();...
Definition: TMethod.cxx:306
void WriteMethod(std::ostream &out, TString &ret, TString &name, TString &params, Bool_t isconst, const char *file, TString &anchor, TString &codeOneLiner)
Write a method, forwarding to TClassDocOutput.
virtual void ReferenceEntity(TSubString &str, TClass *entity, const char *comment=0)
Create a reference to a class documentation page.
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:320
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:656
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual Bool_t IsSortable() const
Definition: TObject.h:131
R__EXTERN TSystem * gSystem
Definition: TSystem.h:557
TString fCurrentMethodTag
Definition: TDocParser.h:99
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
virtual const char * ReplaceSpecialChars(char c)
Replace ampersand, less-than and greater-than character, writing to out.
static void AnchorFromLine(const TString &line, TString &anchor)
Create an anchor from the given line, by hashing it and convertig the hash into a custom base64 strin...
Definition: TDocParser.cxx:380
virtual void NameSpace2FileName(TString &name)
Replace "::" in name by "__" Replace "<", ">", " ", ",", "~", "=" in name by "_" Replace "A::X<A::Y>"...
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:819
virtual Bool_t HandleDirective(TString &keyword, Ssiz_t &pos, TString &word, Ssiz_t &copiedToCommentUpTo)
Process directives to the documentation engine, like "Begin_Html" / "End_Html", "Begin_Macro" / "End_...
Definition: TDocParser.cxx:976
Bool_t fCommentAtBOL
Definition: TDocParser.h:115
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Collection abstract base class.
Definition: TCollection.h:63
const char * GetName() const
Returns name of object.
Definition: TDocDirective.h:49
static Bool_t IsName(UChar_t c)
Check if c is a valid C++ name character.
TClass * fRecentClass
Definition: TDocParser.h:97
unsigned int UInt_t
Definition: RtypesCore.h:42
EvaluateInfo init(std::vector< RooRealProxy > parameters, std::vector< ArrayWrapper * > wrappers, std::vector< double *> arrays, size_t begin, size_t batchSize)
TString fCurrentModule
Definition: TDocParser.h:98
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:887
Ssiz_t Length() const
Definition: TString.h:405
std::map< std::string, Int_t > fMethodCounts
Definition: TDocParser.h:103
Int_t fDirectiveCount
Definition: TDocParser.h:100
TVirtualMutex * GetMakeClassMutex() const
Definition: THtml.h:343
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
void LocateMethodsInHeaderInline(std::ostream &out)
Given fCurrentClass, look for methods in its header file, and extract documentation to out...
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:158
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:28
virtual TMethod * GetMethod() const =0
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4753
virtual bool GetDeclFileName(TClass *cl, Bool_t filesys, TString &out_name) const
Return declaration file name; return the full path if filesys is true.
Definition: THtml.cxx:2097
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
void LocateMethodsInHeaderClassDecl(std::ostream &out)
Given fCurrentClass, look for methods in its header file&#39;s class declaration block, and extract documentation to out, while beautifying the header file in parallel.
const Bool_t kFALSE
Definition: RtypesCore.h:88
void Rehash(Int_t newCapacity)
Rehash the hashlist.
Definition: THashList.cxx:368
virtual void FixupAuthorSourceInfo(TString &authors)
Special author treatment; called when TDocParser::fSourceInfo[kInfoAuthor] is set.
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
int Ssiz_t
Definition: RtypesCore.h:63
TString fSourceInfo[kNumSourceInfos]
Definition: TDocParser.h:121
void SetParameters(const char *params)
Given a string containing parameters in params, we call AddParameter() for each of them...
TString fLineRaw
Definition: TDocParser.h:89
std::set< UInt_t > fExtraLinesWithAnchor
Definition: TDocParser.h:120
TString fLineComment
Definition: TDocParser.h:91
virtual const char * GetTypeName() const
Get type of global variable, e,g.
Definition: TGlobal.cxx:111
#define ClassImp(name)
Definition: Rtypes.h:365
TString fCurrentFile
Definition: TDocParser.h:102
TText * text
virtual void DecorateKeywords(std::ostream &out, const char *text)
Expand keywords in text, writing to out.
Definition: TDocParser.cxx:449
TString fFirstClassDoc
Definition: TDocParser.h:94
unsigned long ULong_t
Definition: RtypesCore.h:51
static std::set< std::string > fgKeywords
Definition: TDocParser.h:125
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
#define R__LOCKGUARD(mutex)
EParseContext Context() const
Definition: TDocParser.h:129
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TBaseClass.cxx:134
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2906
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:399
std::list< UInt_t > fParseContext
Definition: TDocParser.h:105
Int_t Match(const TString &s, UInt_t start=0)
Runs a match on s against the regex &#39;this&#39; was created with.
Definition: TPRegexp.cxx:708
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetEndTag() const =0
virtual TClass * GetClass(const char *name) const
Return pointer to class with name.
Definition: THtml.cxx:2068
char Char_t
Definition: RtypesCore.h:29
TString fLineStripped
Definition: TDocParser.h:90
const TString & GetCopyrightTag() const
Definition: THtml.h:307
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:97
EDocContext fDocContext
Definition: TDocParser.h:104
virtual void RemoveAll(TCollection *col)
Remove all objects in collection col from this collection.
TDocOutput * GetDocOutput() const
Definition: TDocParser.h:173
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
virtual void InitKeywords() const
fill C++ keywords into fgKeywords
TClass * GetClass() const
Definition: TMethod.h:55
void LocateMethods(std::ostream &out, const char *filename, Bool_t lookForSourceInfo=kTRUE, Bool_t useDocxxStyle=kFALSE, Bool_t allowPureVirtual=kFALSE, const char *methodPattern=0, const char *sourceExt=0)
Collect methods from the source or header file called filename.
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:476
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
#define c(i)
Definition: RSha256.hxx:101
virtual TObjLink * LastLink() const
Definition: TList.h:111
void AddClassMethodsRecursively(TBaseClass *bc)
Add accessible (i.e.
Definition: TDocParser.cxx:234
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3299
unsigned char UChar_t
Definition: RtypesCore.h:34
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4260
Definition: first.py:1
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:356
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
const TPathDefinition & GetPathDefinition() const
Return the TModuleDefinition (or derived) object as set by SetModuleDefinition(); create and return a...
Definition: THtml.cxx:1331
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition: TClass.cxx:3695
const Bool_t kTRUE
Definition: RtypesCore.h:87
const Int_t n
Definition: legend1.C:16
char name[80]
Definition: TGX11.cxx:109
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:873
void LocateMethodsInSource(std::ostream &out)
Given fCurrentClass, look for methods in its source file, and extract documentation to out...
virtual void DeleteOutput() const
Definition: TDocDirective.h:73
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
virtual void AddLine(const TSubString &line)=0
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4857
const char * Data() const
Definition: TString.h:364
TString fLineSource
Definition: TDocParser.h:92