Doxygen XLinks
by
V: 2511R0
Website: doxygen
Loading...
Searching...
No Matches
sourcelocationfinder.cpp
1//==================================================================================================
2// This implementation-file is part of DoxygenXLinks - A doxygen post-processor that allows to
3// define smarter <b>Doxygen</b>-links.
4//
5// \emoji :copyright: 2025-2026 A-Worx GmbH, Germany.
6// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#include "jobs.hpp"
9#include "dxl.hpp"
10#include "xlink.hpp"
11#include "dxlapp.hpp"
13#include "ALib.ALox.H"
14#include "ALib.App.H" // TODO(251204 09:14): we need this only for the definition of LOX_LOX.
15 // How can we avoid to include the whole app?
16
17#include <iostream>
18#include <fstream>
19
20using namespace alib;
21using namespace std;
22
23namespace dxl {
24
25 ////----- special doxygen fix: search for "\anchor" and "\name" in one line --------
26 //{
27 // // todo: this is not used anywhere. Do we want to keep it? Is this doxed? Does this make sense?
28 // integer anchorPos= line.IndexOf("anchor");
29 // if ( anchorPos >= 1
30 // && ( line.CharAt(anchorPos-1) == '\\'
31 // || line.CharAt(anchorPos-1) == '@') ) {
32 // anchorPos+=7;
33 //
34 // integer dxlTagPos= line.IndexOf("DXLTAG{", anchorPos);
35 // if ( dxlTagPos > 0
36 // && ( line.CharAt(dxlTagPos-1) == '\\'
37 // || line.CharAt(dxlTagPos-1) == '@') ) {
38 // Substring anchorName= line.Substring(anchorPos, dxlTagPos-anchorPos-1);
39 // anchorName.Trim();
40 // Substring anchorTitle= line.Substring(dxlTagPos+7, line.IndexOfOrLength('}')-1);
41 // anchorTitle.Trim();
42 //
43 // String512 sourceHint;
44 // sourceHint << "Found pattern '@anchor ...@DXLTAG{title}\' in source: "
45 // << path << ':' << lineNo;
46 //
47 // dxl.AddAnchorTitle(anchorName, anchorTitle, sourceHint);
48 // }
49 // }
50 //}
51
52
54 Lox_SetDomain("DXL/SRC/JOB", Scope::Method )
55 Lox_Info( "Reading source file {!Q} of size {}",
57 dxl.Stats.SourceFileSize.fetch_add(int(srcFileNode->Size()));
58
59 Path path;
60 {ALIB_LOCK_SHARED_WITH(dxl.GetSourceTreeLock())
61 srcFileNode.AssembleRealPath(path, lang::Inclusion::Include); }
62
63 // read exclamations applicable to this file once
65 dxl.Exclamations.Get(srcFileNode.Name(), exclamations);
66
68
69 Lox_Info("Reading source file: {}", path )
70 MappedFile& htmlFile= poolWorker->InputFile;
71 std::errc errc= htmlFile.Open(path.Terminate(), srcFileNode->Size(), false);
72 if(errc != std::errc()) {
73 app.cErr->Add(app.cli.ExitCodeDecls.Find(ExitCodes::CantOpenSrcFile).Mapped()->FormatString(),
74 path);
75 app.machine.SetExitCode(ExitCodes::CantOpenSrcFile);
76 return true;
77 }
78 MappedFile::Data<char> mfc= htmlFile.GetData<char>();
79
80 // we want maximum speed and even spare the fast log calls in the loop.
81 Verbosity verbosity;
82 Lox_GetVerbosity(verbosity)
83
84 //------------------------------------------- main loop ------------------------------------------
85 integer lineStartRemaining= mfc.Remaining();
86 int lineNo= 1;
87 String512 linkString;
88
89 while ( !mfc.IsEOF() ) {
90 char c= mfc.Next<NC>();
91 if (c == '\n') { lineNo++; lineStartRemaining= mfc.Remaining(); continue; }
92 if (c != '#' ) { continue; }
93
94 //------------------------------------------ # found -----------------------------------------
95 if (mfc.Remaining() < 4)
96 break;
97
98 //---- 2nd character ----
99 c= mfc.Next<NC>();
100
101 // if double hash is given, remove one hash ##"..." and keep the rest.
102 // Note: This is mainly needed for the documentation of this tool ;-)
103 if (c == '#' ) { continue;}
104
105 // not '"' ?
106 if ( c != '\"' ) {
107 if ( c == '\n')
108 ++lineNo;
109 continue;
110 }
111
112 //---- 3rd character: not an allowed link start? ----
113 c= mfc.Next<NC>();
114 if ( !isalpha(c) && String(".%^_<").IndexOf(c) < 0 ) {
115 if ( c == '\n')
116 ++lineNo;
117 continue;
118 }
119
120 int colNo= int(lineStartRemaining - mfc.Remaining() - 2);
121
122 // search for exclamations
123 { auto exclIt= exclamations.begin();
124 for (; exclIt!=exclamations.end(); ++exclIt )
125 if ( (*exclIt)->Matches(lineNo, colNo ) )
126 break;
127 if (exclIt != exclamations.end()) {
128 continue;
129 } }
130
131 // This seems to be an XLink!
132 bool suppressedAnchor;
133 linkString.Reset(c); {
134 bool foundEnd= false;
135 while (mfc.Remaining()) {
136 c= mfc.Next<NC>();
137 if ( c == '\\') { linkString._<NC>(c); linkString._<NC>(mfc.Next()); continue; }
138 if ( c == '\"') { foundEnd= true; break;}
139 if ( c == '\n') { lineNo++; break; }
140 linkString._<NC>(c);
141 if (linkString.Length() == 511 ) {
142 Lox_Warning( "Found unterminated XLink pattern {!Q} in source file {}:{}:{}",
143 linkString, path, lineNo, colNo )
144 break;
145 } }
146 suppressedAnchor= linkString.CharAtStart() == '%';
147 if ( !foundEnd ) continue;
148 if (suppressedAnchor)
149 linkString[0]= ' ';
150 linkString.Trim();
151 }
152
153 // get or create the XLink
154 XLink* xLink= dxl.RegisterXLink(linkString);
155
156 if (verbosity >= Verbosity::Info)
157 Lox_Info( "Found XLink pattern {!Q} in source file {}:{}:{}",
158 linkString, path, lineNo, colNo )
159
160 // attach this source location to the XLink
161 {ALIB_LOCK_WITH(xLink->Lock)
162 xLink->SourceLocations.emplace_back( srcFileNode, lineNo, colNo ); }
163
164 // attach the XLink to this source file
165 { ALIB_LOCK_WITH(dxl.GetSourceTreeLock())
166 if (!srcFileNode.HasCustomData())
167 srcFileNode.AttachCustomData<XLinkList>(dxl.GetSourceTree().GetAllocator());
168 srcFileNode.GetCustomData<XLinkList>().emplace_back( xLink, lineNo, colNo );
169 } }
170
171 dxl.Stats.SourceFileLines.fetch_add(lineNo);
172 return true;
173}
174} //namespace [dxl]
#define ALIB_LOCK_SHARED_WITH(lock)
#define ALIB_LOCK_WITH(lock)
#define Lox_Info(...)
#define Lox_SetDomain(...)
#define Lox_GetVerbosity(result,...)
#define Lox_Warning(...)
constexpr const TChar * Terminate() const
TAString & Trim(const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
constexpr integer Length() const
TChar CharAtStart() const
integer Remaining() const noexcept
bool IsEOF() const noexcept
std::errc Open(const CPathString &path, std::size_t knownSize=(std::numeric_limits< std::size_t >::max)(), bool disableMMap=false, bool willNeed=true)
Data< T > GetData() const noexcept
class DXLApp
Definition dxlapp.hpp:37
TApp & Get()
lox::Verbosity Verbosity
lang::integer integer
strings::TString< character > String
system::Path Path
system::MappedFile MappedFile
std::vector< T, StdMA< T > > StdVectorMA
LocalString< 512 > String512
todox
Definition doxyfile.cpp:20
alib::StdVectorMA< ResolvedLocation > XLinkList
Definition xlink.hpp:41
@ CantOpenSrcFile
A source file was not found or could not be accessed.
Definition dxl.hpp:99
DXLPoolWorker * poolWorker
The pool worker that executes this job.
alib::filetree::FTFile srcFileNode
The source-file to load and search for DoxygenXLinks links.
Definition jobs.hpp:82