41 if (
line.StartsWith(
"<docanchor")){
66 if ( !parent.Value()->HTMLFile.Equals(actDocAnchor->HTMLFile) ) {
68 Lox_Info(
"Skipping anchor {!Q} in compound {!Q} of type {}, because it has a\n"
69 "different HTML file-target than its parent.\n"
70 " Compound target: {}\n"
71 " DocAnchor Target: {}\n"
72 " In tag-file: @ {}:{}\n"
73 ,actDocAnchor->Name, parent.Name(), parent.Value()->Kind()
74 ,parent.Value()->HTMLFile
75 ,actDocAnchor ->HTMLFile
81 Cursor newChild= parent.CreateChild(actDocAnchor->Name, actDocAnchor);
82 if ( newChild.IsInvalid() ) {
84 parent.AssemblePath(path);
85 Cursor previous= parent.Child(actDocAnchor->Name);
86 Lox_Error(
"Doubly defined anchor {!Q} in compound {!Q} of type {} (ignoring)\n"
87 " First definition @ {}:{}\n"
88 " Second definition @ {3}:{}"
89 ,actDocAnchor->Name, parent.Name(), parent.Value()->Kind()
91 ,previous.Value()->LineNo, actDocAnchor->LineNo )
100 if (!
line.ConsumeChar(
'<') )
102 if (!
line.StartsWith(tagName))
109 if (
line.CharAtStart() ==
' ' ) {
111 bool inString=
false;
112 for (; attrEnd<
line.Length(); ++attrEnd) {
114 if (c ==
'\"' &&
line.CharAt<
NC>(attrEnd - 1) !=
'\\') {
118 if (!inString && c ==
'>' )
121 if ( attrEnd ==
line.Length())
124 line.ConsumeChars<
NC>(attrEnd + 1 );
129 if (
line.CharAtStart() !=
'>')
135 if (
line.EndsWith(
String64(
"</")._<NC>(tagName)._<NC>(
'>')) )
138 if (!
line.EndsWith(
">"))
141 line.ConsumeCharsFromEnd(1);
149 idxStart=
tagAttr.IndexOf(attrName, idxStart);
152 Lox_Error(
"Unexpected Doxygen tag-file format: Missing attribute {!Q}\n"
161 &&
tagAttr.CharAt(idxStart + attrName.
Length() + 1) ==
'\"' )
163 idxStart+= attrName.
Length() + 1;
165 idxStart+= attrName.
Length() + 2;
168 for (; idxEnd<
tagAttr.Length(); ++idxEnd) {
179 if ( idxEnd ==
tagAttr.Length() )
183 return tagAttr.Substring( idxStart, idxEnd-idxStart);
188 if (!
line.ConsumeString(
"<member kind=\"" ))
197 line.ConsumeChar(
'"');
199 if (
line.ConsumeString(
"refid=\"")) {
200 refID =
line.ConsumeToken(
'"');
211 ALIB_ASSERT_ERROR(type.Equals(
"#define"),
"DXL/TAGFILE",
"Expected '#define' as type")
232 if (
nextTag(
"arglist").IsNotEmpty() )
250 if (
nextTag(
"arglist").IsNotEmpty() )
253 if (
line.StartsWith(
"<enumvalue")) {
268 if (
nextTag(
"arglist").IsNotEmpty() )
272 if (!
line.StartsWith(
"</member")) {
297 if (!
line.Equals(
"</member>"))
303 if (!
line.Equals(
"</member>"))
324 "arglist starting with '('", argList);
326 if (member->
Args ==
nullptr)
338 if (!
line.Equals(
"</member>"))
348 Lox_Warning(
"Unexpected member type {} in compound of type {}. Ignoring.",
357 if (
line.Equals(
"</member>"))
359 if (
line.StartsWith(
"<name")) key <<
nextTag(
"name");
366 Lox_Warning(
"Unnamed (generic) member of type {} in compound of type {}. Ignoring.",
367 member->
Kind, compoundType)
378 std::ifstream ifstream;
382 if ( !ifstream.is_open() || errno ) {
400 ALIB_ASSERT_ERROR(parser.line.StartsWith(
"<?xml version='1.0'"),
"DXL/TAGFILE",
"Unknown file format")
403 parser.nextTag(
"tagfile");
404 Lox_Info(
"Doxygen version: ", parser.getAttr(
"doxygen_version") )
405 while( !reader.
IsEOF() ) {
409 if (parser.line.Equals(
"</tagfile>"))
413 if ( parser.tryTag(
"compound").IsNull() ) {
415 FilePath, parser.lineNo,
"compound", parser.line);
420 Substring kindStr= parser.getAttr(
"kind");
423 FilePath, parser.lineNo, parser.lineBuf );
429 String1K compoundTagName = parser.nextTag(
"name");
430 String compoundHtmlFile= parser.allocNextTag(
"filename");
436 int templateArgsSize= 0;
440 Substring compoundNameWithoutTemplateParams= compoundTagName;
441 Substring templateSpecializationArgs=
nullptr;
445 compoundNameWithoutTemplateParams= compoundTagName.
Substring(0, templateStart);
446 compoundNameWithoutTemplateParams.
TrimEnd();
447 templateSpecializationArgs = compoundTagName.
Substring(templateStart);
452 String compoundPathPortion=
nullptr;
454 if ( lastPathPos>=0 ) {
456 "Single colon ':' found in compound name {!Q}", compoundTagName )
457 compoundPathPortion= compoundTagName.
Substring(0, lastPathPos -1);
458 compoundNameWithoutTemplateParams= compoundNameWithoutTemplateParams.
Substring(lastPathPos + 1);
467 Cursor component= pathCursor.CreateChild(pathComponent,
nullptr);
471 if ( component.IsValid()) {
473 pathCursor= component;
476 pathCursor.GoToChild(tok.
Actual);
487 Cursor compoundCursor= pathCursor.CreateChild(compoundKey,
nullptr);
488 if ( compoundCursor.IsInvalid()) {
489 compoundCursor= pathCursor.Child(compoundKey);
493 compoundKey, compoundPathPortion,
FilePath,
494 pathCursor.Child(compoundKey).Value()->LineNo, parser.lineNo);
501 compoundCursor.Value()=
502 tagNamespace=
ma().New<
TGTNamespace>(compoundHtmlFile, parser.lineNo);
506 compoundCursor.Value()=
507 tagRecord=
ma().New<
TGTRecord>(
ma, kind, compoundHtmlFile, parser.lineNo);
523 parser.addDocAnchors(compoundCursor);
525 if ( parser.line.StartsWith(
"<member kind=") ) {
527 TGTMember* member= parser.readMember(key, kind);
528 if (!member)
continue;
530 Cursor memberChild= compoundCursor.CreateChild(key, member);
531 if ( memberChild.IsInvalid() ) {
532 Target* existingValue= compoundCursor.Child(key).Value();
541 Lox_Error(
"Doubly defined member function.\n"
542 "This happens with overloaded template functions that use keyword requires.\n"
543 "To fix this, dox only one function and include in the dox that\n"
544 "different versions for different requirements exist.\n"
545 " Function: {}::{}.\n"
546 " Tag-file first occurence: {}:{}.\n"
547 " Tag-file this occurence: {2}:{}.\n"
577 parser.addDocAnchors(memberChild);
580 while (parser.line.StartsWith(
"<enumvalue")) {
581 int lNo= parser.lineNo;
582 String256 elemName= parser.parseTag(
"enumvalue");
584 String(
ma, parser.parseAttr(
"file")), lNo );
586 Cursor elementCursor= memberChild.CreateChild(elemName, enumElementTag);
587 if ( elementCursor.IsInvalid() ) {
589 elemName, compoundPathPortion,
FilePath,
590 memberChild.Child(elemName).Value()->LineNo, parser.lineNo );
596 if (!parser.line.Equals(
"</member>"))
598 FilePath,parser.lineNo,
"/member", parser.line);
605 if ( parser.line.StartsWith(
"<templarg" ) ){
606 templateArgs[templateArgsSize++]=
613 if ( parser.line.StartsWith(
"<class" )
614 && parser.line.EndsWith(
"</class>") )
continue;
616 if ( parser.line.Equals(
"</compound>") )
break;
619 if ( parser.line.StartsWith(
"<base" ) ) {
621 "Base type information found for non-record type")
622 tagRecord->
BaseTypes.push_back(parser.allocTag(
"base"));
627 if ( parser.line.StartsWith(
"<namespace" ) )
continue;
628 if ( parser.line.StartsWith(
"<concept" ) )
continue;
632 FilePath,parser.lineNo,
"/compound", parser.line);
636 if (templateArgsSize) {
638 "Template args found for non-record type")
642 for (
int i= 0; i<templateArgsSize; ++i)
652 path = parser.nextTag(
"path");
654 dirCursor.GoToCreatedPathIfNotExistent(path, &filePathComponentTag);
657 dirCursor= dirCursor.CreateChild(name,
ma().New<TGTDir>( parser.allocNextTag(
"filename"),
662 parser.addDocAnchors(dirCursor);
666 if ( parser.line.StartsWith(
"<file>") )
continue;
667 if ( parser.line.StartsWith(
"<dir>") )
continue;
668 if ( parser.line.Equals(
"</compound>") )
673 FilePath,parser.lineNo,
"/compound", parser.line);
682 path = parser.nextTag(
"path");
684 fileCursor.GoToCreatedPathIfNotExistent(path, &filePathComponentTag);
692 fileCursor= fileCursor.CreateChild(name,
ma().New<TGTFile>(
693 parser.allocNextTag(
"filename"), parser.lineNo));
696 parser.addDocAnchors(fileCursor);
698 if ( parser.line.StartsWith(
"<member kind=") ) {
700 TGTMember* member= parser.readMember(key, kind);
701 if (!member)
continue;
702 Cursor memberChild= fileCursor.CreateChild(key, member);
703 if ( memberChild.IsInvalid() ) {
704 fileCursor.AssemblePath(path);
706 Cursor previous= fileCursor.Child(key);
712 || !previous.Value()->HTMLFile.Equals(member->
HTMLFile) ) {
715 "This happens when a preprocessor constant or macro is defined twice within\n"
716 "the same source file. This is not supported by Doxygen.\n"
717 "Instead, exclude the second (and further) occurrences in the same file from\n"
718 "doxygen and add all different uses to the first definition.\n"
719 " Preprocessor define: {}::{}.\n"
720 " Tag-file first occurence: {}:{}.\n"
721 " Tag-file this occurence: {2}:{}.\n"
723 , previous.Value()->LineNo
726 Lox_Error(
"Doubly defined member {!Q} in tag-file path {}:1\n"
727 " First definition @ {}:{}\n"
728 " Second definition @ {2}:{}", key, path,
FilePath,
729 previous.Value()->LineNo, member->
LineNo)
738 previous.Value()->LineNo, member->
LineNo);
743 parser.addDocAnchors(memberChild);
748 if ( parser.line.Equals(
"</compound>") )
759 if ( parser.line.StartsWith(
"<includes" ) )
continue;
760 if ( parser.line.StartsWith(
"<concept" ) )
continue;
761 if ( parser.line.StartsWith(
"<class" ) )
continue;
762 if ( parser.line.StartsWith(
"<namespace" ) )
continue;
766 FilePath,parser.lineNo,
"/compound", parser.line);
773 String title = parser.allocNextTag(
"title");
776 Cursor groupCursor=
Root().CreateChild(name,
ma().New<TGTGroup>(
777 parser.allocNextTag(
"filename"), parser.lineNo, title));
780 parser.addDocAnchors(groupCursor);
783 if ( parser.line.StartsWith(
"<member kind=") ) {
785 TGTMember* member= parser.readMember(key, kind);
786 if (!member)
continue;
788 Cursor memberChild= groupCursor.CreateChild(key, member);
789 if ( memberChild.IsInvalid() ) {
791 groupCursor.AssemblePath(path);
792 Cursor previous= groupCursor.Child(key);
793 Lox_Warning(
"Doubly defined member {!Q} in tag-file path {}:1\n"
794 " First definition @ {}:{}\n"
795 " Second definition @ {2}:{}"
797 ,previous.Value()->LineNo, member->
LineNo )
801 parser.addDocAnchors(memberChild);
806 if ( parser.line.Equals(
"</compound>") )
817 FilePath,parser.lineNo,
"/compound", parser.line);
824 String title = parser.allocNextTag(
"title");
827 Cursor pageCursor=
Root().CreateChild(name,
ma().New<TGTPage>(
828 parser.allocNextTag(
"filename"), parser.lineNo, title));
832 parser.addDocAnchors(pageCursor);
834 if ( parser.line.Equals(
"</compound>") )
838 FilePath,parser.lineNo,
"/compound", parser.line);
845 auto htmlFile= parser.allocNextTag(
"filename");
848 int qtyCreated= cursor.GoToCreatedPathIfNotExistent(name, &filePathComponentTag);
849 if ( qtyCreated == 0 ) {
850 Cursor previous= cursor.Child(name);
852 || previous.Value()->HTMLFile.Equals(htmlFile) )
854 name,
FilePath, previous.Value()->LineNo, parser.lineNo);
856 " First definition @ {}:{}\n"
857 " Second definition @ {2}:{}",
858 name,
FilePath, previous.Value()->LineNo, parser.lineNo)
862 cursor.Value()=
ma().New<
TGTConcept>(htmlFile, parser.lineNo);
864 if (!parser.line.Equals(
"</compound>"))
866 FilePath, parser.lineNo,
"/compound", parser.line);
876 Lox_Verbose(
"Finished reading tag-file: {}, maximum line width: ",
FilePath, parser.maxWidth )
877 ALIB_ASSERT_ERROR(parser.maxWidth < 1024,
"DXL/TAGFILE",
"Line buffer to small.")
881 if ( branch.IsInvalid())
897 switch (tag.Kind()) {
900 " Documented in: {}\n"
901 " Tag-file location: {}:{}",
903 tag.HTMLFile,
FilePath, tag.LineNo )
932 ALIB_ERROR(
"DXL/DUMP",
"Page/Group should not be read today" )
945 stit.
Node().Name(), target)
#define ALIB_ALLOW_SPARSE_ENUM_SWITCH
#define ALIB_CALLER_NULLED
#define ALIB_ASSERT(cond, domain)
#define ALIB_ERROR(domain,...)
#define ALIB_POP_ALLOWANCE
#define ALIB_ASSERT_ERROR(cond, domain,...)
#define ALIB_ALLOW_MISSING_FIELD_INITIALIZERS
#define Lox_SetPrefix(...)
#define Lox_SetDomain(...)
#define Lox_GetVerbosity(result,...)
unsigned CurrentDepth() const
void Initialize(CursorType startNode, lang::Inclusion includeStartNode)
const TStringTree::NameType Path() const
void SetPathGeneration(lang::Switch pathGeneration)
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
TAString & DeleteStart(const TString< TChar > &deleteIfMatch)
constexpr integer Length() const
TChar CharAtStart() const
TChar CharAt(integer idx) const
constexpr bool IsNotEmpty() const
integer IndexOf(const TString &needle, integer startIdx=0, integer endIdx=strings::MAX_LEN) const
integer LastIndexOf(TChar needle, integer startIndex=MAX_LEN) const
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
bool Equals(const TString< TChar > &rhs) const
constexpr bool IsNull() const
bool StartsWith(const TString &needle) const
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
TSubstring & Trim(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
TSubstring & TrimEnd(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
void SetStream(::std::istream *is)
TSubstring< TChar > Actual
TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
alib::system::PathString FilePath
The path to the doxygenTagFile.
alib::MonoAllocator ma
The allocator used for the parent #"StringTree" and for the hashtable in the field map.
void DumpTree(Node branch)
void ReplaceToTreeSeparator(alib::AString &buffer, Target::Kinds kind, alib::integer startPos=0)
void ReplaceFromTreeSeparator(alib::AString &buffer, Target::Kinds kind, alib::integer startPos=0)
void loadTagFile()
Loads the tag-file. This is called by Load.
int StatCtdLines
Statistics on the number of lines in the tag-file.
Index(const alib::system::PathString &tagFilePath, const alib::String &baseURL, bool isMainTagFile)
bool IsA(Kinds aKind) const
static size_t MAX_TEMPLATE_ARGS
alib::String HTMLFile
The HTML file that this target links to (or into).
Kinds
Enumerates the kinds of compounds found in a the Doxygen tagfile.
@ COMPOUND
Mask to identify compound types.
@ Struct
Denotes a struct.
@ Function
Denotes a namespace- or member-function.
@ Variable
Denotes a namespace- or member-variable.
@ Typedef
Denotes a type definition.
@ File
Denotes a source file.
@ EnumElement
Denotes an enumeration element.
@ Concept
Denotes a C++20 concept.
@ Macro
Denotes a preprocessor definition.
@ Dir
Denotes a source folder.
@ Enumeration
Denotes an enumeration.
@ FILEPATH_COMPONENT
A node of a file path (not a doxygen kind).
@ Namespace
Denotes a namespace.
int LineNo
The line number in the Doxygen tag-file where this entity is defined.
bool Parse(strings::TSubstring< TChar > &input, TEnum &result)
constexpr PathCharType DIRECTORY_SEPARATOR
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
constexpr String NULL_STRING
strings::compatibility::std::IStreamReader IStreamReader
strings::util::TTokenizer< character > Tokenizer
LocalString< 64 > String64
constexpr const String EMPTY_STRING
monomem::TLocalAllocator< 2 > LocalAllocator2K
strings::TString< character > String
strings::TSubstring< character > Substring
LocalString< 1024 > String1K
exceptions::Exception Exception
LocalString< 128 > String128
LocalString< 256 > String256
strings::TAString< character, lang::HeapAllocator > AString
characters::character character
containers::StringTreeIterator< TTree > StringTreeIterator
LocalString< 512 > String512
@ DuplicateChildName
todox
@ UnexpectedXMLValue
todox
void ConvertHTMLEntitiesToAscii(alib::AString &buffer)
const TGT * Cast(const Index::Node &node)
@ TagFileNotFound
Doxygen tag-file not created, yet. Needs a second run.
constexpr const TChar * Buffer() const noexcept
The cursor type of the #"StringTree".
Internal struct that parses a tag-file. Used by the method loadTagFile.
alib::String nextTag(const alib::String &tagName)
alib::system::PathString FilePath
The path to the doxygenTagFile.
TGTMember * readMember(alib::String512 &key, Target::Kinds compoundKind)
todo: add parameter parent and if html file is the same, then re-use instead of allocation.
alib::IStreamReader & reader
A referenced to the ALib text file reader tool.
alib::Substring tagAttr
The current tag attributes. Set by parseTag.
Parser(Index &parent, alib::IStreamReader &pReader, const alib::String &pFilePath)
alib::lox::Verbosity verbosity
The log verbosity of the parser (used for performance optimization).
alib::ListMA< TGTDocAnchor * > actDocAnchors
Set by nextLine() in case it finds a <docanchor>.
void addDocAnchors(Cursor &parent)
alib::Substring line
A parser for the currently read line.
alib::MonoAllocator & ma
A referenced to the allocator of outer class Index.
alib::String allocNextTag(const alib::String &tagName)
alib::String allocTag(const alib::String &tagName)
int lineNo
The current line number when reading.
alib::String2K lineBuf
The buffer of the line currently read.
alib::String parseTag(const alib::String &tagName)
alib::String parseAttr(const alib::String &attrName, bool isOptional=false)
alib::integer maxWidth
The maximum line width found.
XLink target information for C++ concepts.
XLink target information for C++ enum elements.
XLink target information for C++ enums.
alib::String Type
The underlying type of the enum.
XLink target information for C++ namespace- and member-functions.
FunctionArguments * Args
The list of arguments.
alib::String Type
The return type of the function or method.
alib::String Qualifiers
Additional qualifiers like const or nothrow.
Target::Kinds Kind
The kind of the member, which was not fully read.
XLink target information for C++ preprocessor definitions.
alib::String Anchor
The HTML anchor.
alib::String RefID
This ID is (sometimes) set if the member is read from a Doxygen group.
XLink target information for C++ namespaces.
XLink target information for C++ structs, classes and unions.
TemplateArguments * SpecializationArgs
TemplateArguments * TemplateArgs
Template arguments provided with tags <templarg>.
alib::ListMA< alib::String > BaseTypes
The base type of the record.
XLink target information for type definitions.
alib::String Type
The type of the definition.
XLink target information for C++ namespace- and member-variables.
alib::String Subscript
The subscript of the variable.
alib::String Type
The type of the variable.
void Print(alib::AString &dest)
static FunctionArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
int Count
The number of arguments.
static TemplateArguments * PARSE(alib::MonoAllocator &ma, alib::Substring &parser)
alib::String * Arguments
An array of length Count of strings.