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 "dxlapp.hpp"
11#include "ALib.Files.TextFile.H"
12#include "ALib.ALox.H"
13#include "ALib.App.H" // TODO(251204 09:14): we need this only for the definition of LOX_LOX.
14 // How can we avoid to include the whole app?
15
16#include <iostream>
17#include <fstream>
18
19using namespace alib;
20using namespace std;
21
22namespace dxl {
23
24 ////----- special doxygen fix: search for "\anchor" and "\name" in one line --------
25 //{
26 // // todo: this is not used anywhere. Do we want to keep it? Is this doxed? Does this make sense?
27 // integer anchorPos= line.IndexOf("anchor");
28 // if ( anchorPos >= 1
29 // && ( line.CharAt(anchorPos-1) == '\\'
30 // || line.CharAt(anchorPos-1) == '@') ) {
31 // anchorPos+=7;
32 //
33 // integer dxlTagPos= line.IndexOf("DXLTAG{", anchorPos);
34 // if ( dxlTagPos > 0
35 // && ( line.CharAt(dxlTagPos-1) == '\\'
36 // || line.CharAt(dxlTagPos-1) == '@') ) {
37 // Substring anchorName= line.Substring(anchorPos, dxlTagPos-anchorPos-1);
38 // anchorName.Trim();
39 // Substring anchorTitle= line.Substring(dxlTagPos+7, line.IndexOfOrLength('}')-1);
40 // anchorTitle.Trim();
41 //
42 // String512 sourceHint;
43 // sourceHint << "Found pattern '@anchor ...@DXLTAG{title}\' in source: "
44 // << path << ':' << lineNo;
45 //
46 // dxl.AddAnchorTitle(anchorName, anchorTitle, sourceHint);
47 // }
48 // }
49 //}
50
51
53 Lox_SetDomain("DXL/SRC/JOB", Scope::Method )
54 Lox_Info( "Reading source file {!Q} of size {}",
56 dxl.Stats.SourceFileSize.fetch_add(int(srcFileNode->Size()));
57
58 Path path;
59 {ALIB_LOCK_SHARED_WITH(dxl.GetSourceTreeLock())
60 srcFileNode.AssembleRealPath(path, lang::Inclusion::Include); }
61
62 // read exclamations applicable to this file once
64 dxl.Exclamations.Get(srcFileNode.Name(), exclamations);
65
67
68 Lox_Info("Reading source file: {}", path )
69 MappedFile& htmlFile= poolWorker->InputFile;
71 try {
72 mfc= htmlFile.Open(path.Terminate(), srcFileNode->Size(), false);
73 } catch (std::exception&) {
74 app.cErr->Add(app.cli.ExitCodeDecls.Find(ExitCodes::CantOpenSrcFile).Mapped()->FormatString(),
75 path);
76 app.machine.SetExitCode(ExitCodes::CantOpenSrcFile);
77 return true;
78 }
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 size_t lineStartRemaining= mfc.Remaining();
86 int lineNo= 1;
87 String512 linkString;
88
89 while ( !mfc.IsEOF() ) {
90 char c= char( 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= char(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= char(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= char(mfc.Next<NC>());
137 if ( c == '\\') { linkString._<NC>(c); linkString._<NC>(char(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 }
147 suppressedAnchor= linkString.CharAtStart() == '%';
148 if ( !foundEnd ) continue;
149 if (suppressedAnchor)
150 linkString[0]= ' ';
151 linkString.Trim();
152 }
153
154 // get or create the XLink
155 XLink* xLink= dxl.RegisterXLink(linkString);
156
157 if (verbosity >= Verbosity::Info)
158 Lox_Info( "Found XLink pattern {!Q} in source file {}:{}:{}",
159 linkString, path, lineNo, colNo )
160
161 // attach this source location to the XLink
162 {ALIB_LOCK_WITH(xLink->Lock)
163 xLink->SourceLocations.emplace_back( srcFileNode, lineNo, colNo ); }
164
165 // attach the XLink to this source file
166 { ALIB_LOCK_WITH(dxl.GetSourceTreeLock())
167 if (!srcFileNode.HasCustomData())
168 srcFileNode.AttachCustomData<XLinkList>(dxl.GetSourceTree().GetAllocator());
169 srcFileNode.GetCustomData<XLinkList>().emplace_back( xLink, lineNo, colNo );
170 }
171 }
172
173 dxl.Stats.SourceFileLines.fetch_add(lineNo);
174 return true;
175}
176} //namespace [dxl]
177
#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
class DXLApp
Definition dxlapp.hpp:37
bool IsEOF() const noexcept
std::size_t Remaining() const noexcept
Data Open(const char *path, std::size_t knownSize=std::numeric_limits< std::size_t >::max(), bool disableMMap=false)
TApp & Get()
lox::Verbosity Verbosity
strings::TString< character > String
system::Path Path
std::vector< T, StdMA< T > > StdVectorMA
LocalString< 512 > String512
todox
Definition doxyfile.cpp:20
alib::StdVectorMA< ResolvedLocation > XLinkList
Definition xlink.hpp:40
@ 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::files::File srcFileNode
The source-file to load and search for DoxygenXLinks links.
Definition jobs.hpp:82