Doxygen
Loading...
Searching...
No Matches
commentscan.l
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16%option never-interactive
17%option prefix="commentscanYY"
18%option reentrant
19%option extra-type="struct commentscanYY_state *"
20%top{
21#include <stdint.h>
22// forward declare yyscan_t to improve typesafety
23#define YY_TYPEDEF_YY_SCANNER_T
24struct yyguts_t;
25typedef yyguts_t *yyscan_t;
yyguts_t * yyscan_t
Definition code.l:24
26}
27
28%{
29
30/*
31 * includes
32 */
33
34#include <map>
35#include <stack>
36#include <string>
37#include <mutex>
38#include <functional>
39#include <unordered_map>
40#include <algorithm>
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <assert.h>
45#include <ctype.h>
46
47#include "dstring.h"
48#include "fileinfo.h"
49#include "cite.h"
50#include "commentscan.h"
51#include "condparser.h"
52#include "config.h"
53#include "debug.h"
54#include "docgroup.h"
55#include "doxygen.h"
56#include "entry.h"
57#include "formula.h"
58#include "language.h"
59#include "mermaid.h"
60#include "message.h"
61#include "parserintf.h"
62#include "reflist.h"
63#include "section.h"
64#include "regex.h"
65#include "util.h"
66#include "trace.h"
67#include "stringutil.h"
68#include "markdown.h"
69
70// forward declarations
71static bool handleBrief(yyscan_t yyscanner,const DString &, const StringVector &);
72static bool handleFn(yyscan_t yyscanner,const DString &, const StringVector &);
73static bool handleDef(yyscan_t yyscanner,const DString &, const StringVector &);
74static bool handleOverload(yyscan_t yyscanner,const DString &, const StringVector &);
75static bool handleEnum(yyscan_t yyscanner,const DString &, const StringVector &);
76static bool handleDefGroup(yyscan_t yyscanner,const DString &, const StringVector &);
77static bool handleAddToGroup(yyscan_t yyscanner,const DString &, const StringVector &);
78static bool handleWeakGroup(yyscan_t yyscanner,const DString &, const StringVector &);
79static bool handleRequirement(yyscan_t yyscanner,const DString &, const StringVector &);
80static bool handleSatisfies(yyscan_t yyscanner,const DString &, const StringVector &);
81static bool handleVerifies(yyscan_t yyscanner,const DString &, const StringVector &);
82static bool handleNamespace(yyscan_t yyscanner,const DString &, const StringVector &);
83static bool handlePackage(yyscan_t yyscanner,const DString &, const StringVector &);
84static bool handleConcept(yyscan_t yyscanner,const DString &, const StringVector &);
85static bool handleClass(yyscan_t yyscanner,const DString &, const StringVector &);
86static bool handleHeaderFile(yyscan_t yyscanner,const DString &, const StringVector &);
87static bool handleProtocol(yyscan_t yyscanner,const DString &, const StringVector &);
88static bool handleCategory(yyscan_t yyscanner,const DString &, const StringVector &);
89static bool handleUnion(yyscan_t yyscanner,const DString &, const StringVector &);
90static bool handleStruct(yyscan_t yyscanner,const DString &, const StringVector &);
91static bool handleInterface(yyscan_t yyscanner,const DString &, const StringVector &);
92static bool handleIdlException(yyscan_t yyscanner,const DString &, const StringVector &);
93static bool handlePage(yyscan_t yyscanner,const DString &, const StringVector &);
94static bool handleMainpage(yyscan_t yyscanner,const DString &, const StringVector &);
95static bool handleFile(yyscan_t yyscanner,const DString &, const StringVector &);
96static bool handleDir(yyscan_t yyscanner,const DString &, const StringVector &);
97static bool handleExample(yyscan_t yyscanner,const DString &, const StringVector &);
98static bool handleDetails(yyscan_t yyscanner,const DString &, const StringVector &);
99static bool handleRaiseWarning(yyscan_t yyscanner,const DString &, const StringVector &);
100static bool handleNoop(yyscan_t yyscanner,const DString &, const StringVector &);
101static bool handleName(yyscan_t yyscanner,const DString &, const StringVector &);
102static bool handleTodo(yyscan_t yyscanner,const DString &, const StringVector &);
103static bool handleTest(yyscan_t yyscanner,const DString &, const StringVector &);
104static bool handleBug(yyscan_t yyscanner,const DString &, const StringVector &);
105static bool handleSubpage(yyscan_t yyscanner,const DString &s, const StringVector &);
106static bool handleDeprecated(yyscan_t yyscanner,const DString &, const StringVector &);
107static bool handleXRefItem(yyscan_t yyscanner,const DString &, const StringVector &);
108static bool handleRelated(yyscan_t yyscanner,const DString &, const StringVector &);
109static bool handleRelatedAlso(yyscan_t yyscanner,const DString &, const StringVector &);
110static bool handleMemberOf(yyscan_t yyscanner,const DString &, const StringVector &);
111static bool handleRefItem(yyscan_t yyscanner,const DString &, const StringVector &);
112static bool handleSection(yyscan_t yyscanner,const DString &, const StringVector &);
113static bool handleAnchor(yyscan_t yyscanner,const DString &, const StringVector &);
114static bool handleImage(yyscan_t yyscanner,const DString &, const StringVector &);
115static bool handleCite(yyscan_t yyscanner,const DString &, const StringVector &);
116static bool handleFormatBlock(yyscan_t yyscanner,const DString &, const StringVector &);
117static bool handleMermaidFile(yyscan_t yyscanner,const DString &s,const StringVector &);
118static bool handleAddIndex(yyscan_t yyscanner,const DString &, const StringVector &);
119static bool handleIf(yyscan_t yyscanner,const DString &, const StringVector &);
120static bool handleIfNot(yyscan_t yyscanner,const DString &, const StringVector &);
121static bool handleElseIf(yyscan_t yyscanner,const DString &, const StringVector &);
122static bool handleElse(yyscan_t yyscanner,const DString &, const StringVector &);
123static bool handleEndIf(yyscan_t yyscanner,const DString &, const StringVector &);
124static bool handleIngroup(yyscan_t yyscanner,const DString &, const StringVector &);
125static bool handleNoSubGrouping(yyscan_t yyscanner,const DString &, const StringVector &);
126static bool handleShowInitializer(yyscan_t yyscanner,const DString &, const StringVector &);
127static bool handleHideInitializer(yyscan_t yyscanner,const DString &, const StringVector &);
128static bool handleCallgraph(yyscan_t yyscanner,const DString &, const StringVector &);
129static bool handleHideCallgraph(yyscan_t yyscanner,const DString &, const StringVector &);
130static bool handleCallergraph(yyscan_t yyscanner,const DString &, const StringVector &);
131static bool handleHideCallergraph(yyscan_t yyscanner,const DString &, const StringVector &);
132static bool handleIncludegraph(yyscan_t yyscanner,const DString &, const StringVector &);
133static bool handleIncludedBygraph(yyscan_t yyscanner,const DString &, const StringVector &);
134static bool handleShowEnumValues(yyscan_t yyscanner,const DString &, const StringVector &);
135static bool handleHideEnumValues(yyscan_t yyscanner,const DString &, const StringVector &);
136static bool handleShowInlineSource(yyscan_t yyscanner,const DString &, const StringVector &);
137static bool handleHideInlineSource(yyscan_t yyscanner,const DString &, const StringVector &);
138static bool handleHideIncludegraph(yyscan_t yyscanner,const DString &, const StringVector &);
139static bool handleHideIncludedBygraph(yyscan_t yyscanner,const DString &, const StringVector &);
140static bool handleDirectoryGraph(yyscan_t yyscanner,const DString &, const StringVector &);
141static bool handleHideDirectoryGraph(yyscan_t yyscanner,const DString &, const StringVector &);
142static bool handleCollaborationgraph(yyscan_t yyscanner,const DString &, const StringVector &);
143static bool handleHideCollaborationgraph(yyscan_t yyscanner,const DString &, const StringVector &);
144static bool handleInheritanceGraph(yyscan_t yyscanner,const DString &, const StringVector &);
145static bool handleHideInheritanceGraph(yyscan_t yyscanner,const DString &, const StringVector &);
146static bool handleReferencedByRelation(yyscan_t yyscanner,const DString &, const StringVector &);
147static bool handleHideReferencedByRelation(yyscan_t yyscanner,const DString &, const StringVector &);
148static bool handleReferencesRelation(yyscan_t yyscanner,const DString &, const StringVector &);
149static bool handleHideReferencesRelation(yyscan_t yyscanner,const DString &, const StringVector &);
150static bool handleGroupgraph(yyscan_t yyscanner,const DString &, const StringVector &);
151static bool handleHideGroupgraph(yyscan_t yyscanner,const DString &, const StringVector &);
152static bool handleInternal(yyscan_t yyscanner,const DString &, const StringVector &);
153static bool handleStatic(yyscan_t yyscanner,const DString &, const StringVector &);
154static bool handlePure(yyscan_t yyscanner,const DString &, const StringVector &);
155static bool handlePrivate(yyscan_t yyscanner,const DString &, const StringVector &);
156static bool handlePrivateSection(yyscan_t yyscanner,const DString &, const StringVector &);
157static bool handleProtected(yyscan_t yyscanner,const DString &, const StringVector &);
158static bool handleProtectedSection(yyscan_t yyscanner,const DString &, const StringVector &);
159static bool handlePublic(yyscan_t yyscanner,const DString &s, const StringVector &);
160static bool handlePublicSection(yyscan_t yyscanner,const DString &s, const StringVector &);
161static bool handleQualifier(yyscan_t yyscanner,const DString &, const StringVector &);
162static bool handleToc(yyscan_t yyscanner,const DString &s, const StringVector &);
163static bool handleInherit(yyscan_t yyscanner,const DString &, const StringVector &);
164static bool handleExtends(yyscan_t yyscanner,const DString &, const StringVector &);
165static bool handleCopyDoc(yyscan_t yyscanner,const DString &, const StringVector &);
166static bool handleCopyBrief(yyscan_t yyscanner,const DString &, const StringVector &);
167static bool handleCopyDetails(yyscan_t yyscanner,const DString &, const StringVector &);
168static bool handleParBlock(yyscan_t yyscanner,const DString &, const StringVector &);
169static bool handleEndParBlock(yyscan_t yyscanner,const DString &, const StringVector &);
170static bool handleParam(yyscan_t yyscanner,const DString &, const StringVector &);
171static bool handleRetval(yyscan_t yyscanner,const DString &, const StringVector &);
172static bool handleFileInfo(yyscan_t yyscanner,const DString &cmdName, const StringVector &optList);
173static bool handleFileInfoSection(yyscan_t yyscanner,const DString &cmdName, const StringVector &optList);
174static bool handleFileInfoResult(yyscan_t yyscanner,const DString &, const StringVector &optList, bool isSection);
175static bool handleLineInfo(yyscan_t yyscanner,const DString &, const StringVector &);
176static bool handleModule(yyscan_t yyscanner,const DString &, const StringVector &);
177static bool handleIFile(yyscan_t yyscanner,const DString &, const StringVector &);
178static bool handleILine(yyscan_t yyscanner,const DString &, const StringVector &);
179static bool handleIRaise(yyscan_t yyscanner,const DString &, const StringVector &);
180static bool handleIPrefix(yyscan_t yyscanner,const DString &, const StringVector &);
181
182[[maybe_unused]] static const char *stateToString(int state);
183
184static DString fileInfoLookup(const FileInfo &fi,const std::string &name);
185
186typedef bool (*DocCmdFunc)(yyscan_t yyscanner,const DString &name, const StringVector &optList);
188
190{
191 Invisible, //!< command sets some property but does not appear in the output.
192 Inline, //!< command appears inline in the output which can be a brief description.
193 Block, //!< command starts a new paragraphs / ends a brief description.
194 XRef //!< command is a cross reference (todo, bug, test, deprecated, xrefitem).
195};
196
198{
199 Allowed, //!< command is allowed without restrictions in section title
200 Replace, //!< command will be handled in here / needs special handling here
201 Escape, //!< command is not-allowed in section title, it will be escaped
202 Break //!< command is not-allowed in section title, it will end the section title
203};
204
212
213// map of command to handler function
214static const std::unordered_map< std::string, DocCmdMap > docCmdMap =
215{
216 // command name handler function command spacing section handling
220 { "arg", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
221 { "attention", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
222 { "author", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
223 { "authors", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
237 { "copyright", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
238 { "date", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
243 { "diafile", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
246 { "docbookinclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
248 { "dontinclude", { nullptr, CommandSpacing::Invisible, SectionHandling::Break }},
250 { "dotfile", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
253 { "endcode", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
254 { "enddocbookonly", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
255 { "enddot", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
256 { "endhtmlonly", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
257 { "endicode", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
259 { "endlatexonly", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
260 { "endlink", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
261 { "endmanonly", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
262 { "endmsc", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
263 { "endmermaid", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
265 { "endrtfonly", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
266 { "endsecreflist", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
267 { "enduml", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
268 { "endverbatim", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
269 { "endxmlonly", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
272 { "exception", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
292 { "htmlinclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
304 { "important", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
305 { "include", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
308 { "includelineno", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
314 { "invariant", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
318 { "latexinclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
320 { "li", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
321 { "line", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
322 { "line", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
326 { "maninclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
331 { "mscfile", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
338 { "note", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
342 { "par", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
346 { "plantumlfile", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
347 { "post", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
348 { "pre", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
365 { "remark", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
366 { "remarks", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
368 { "result", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
369 { "return", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
370 { "returns", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
372 { "rtfinclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
374 { "sa", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
376 { "secreflist", { nullptr, CommandSpacing::Invisible, SectionHandling::Break }},
378 { "see", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
380 { "showdate", { nullptr, CommandSpacing::Inline, SectionHandling::Allowed }},
386 { "since", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
387 { "skip", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
388 { "skipline", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
389 { "snippet", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
390 { "snippetlineno", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
401 { "throw", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
402 { "throws", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
404 { "tparam", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
407 { "until", { nullptr, CommandSpacing::Block, SectionHandling::Escape }},
408 { "until", { nullptr, CommandSpacing::Invisible, SectionHandling::Escape }},
411 { "verbinclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
413 { "version", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
414 { "vhdlflow", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
415 { "warning", { nullptr, CommandSpacing::Block, SectionHandling::Break }},
417 { "xmlinclude", { nullptr, CommandSpacing::Inline, SectionHandling::Break }},
420};
421
422#define YY_NO_INPUT 1
423#define YY_NO_UNISTD_H 1
424#define YY_NEVER_INTERACTIVE 1
425
426
436
444
451
452/* -----------------------------------------------------------------
453 *
454 * statics
455 */
456
463
464using HtmlContextStack = std::vector<HtmlContextInfo>;
465
467{
468 OutlineParserInterface *langParser = nullptr; // the language parser that is calling us
469 DString inputString; // input string
470 DString currentCmd; // the command used
472 int inputPosition = 0; // read pointer
473 DString fileName; // file name that is read from
474 int lineNr = 0; // line number in the input
475 int raiseLevel = 0; // section level raise amount
476 DString raisePrefix; // section label to append
477 bool inBody = false; // was the comment found inside the body of a function?
478 OutputContext inContext; // are we inside the brief, details or xref part
479 bool briefEndsAtDot = false; // does the brief description stop at a dot?
480 DString formulaText; // Running text of a formula
481 DString formulaPreText; // Start command of a formula
482 DString formulaPostText; // End command of a formula
483 DString formulaEnv; // environment name
484 int formulaNewLines = 0; // amount of new lines in the formula
485 DString *pOutputString = nullptr; // pointer to string to which the output is appended.
486 DString outputXRef; // temp argument of todo/test/../xrefitem commands
487 DString blockName; // preformatted block name (e.g. verbatim, latexonly,...)
488 XRefKind xrefKind = XRef_Item; // kind of cross-reference command
490 GuardType guardType = Guard_If; // kind of guards for conditional section
491 DString functionProto; // function prototype
492 GuardedSectionStack *guards = nullptr; // tracks nested conditional sections (if,ifnot,..)
493 Entry *current = nullptr; // working entry
494
495 bool needNewEntry = false;
497
505 Protection protection = Protection::Public;
506
507 bool xrefAppendFlag = false;
508 bool inGroupParamFound = false;
509 int braceCount = 0;
510 bool insidePre = false;
511 bool parseMore = false;
512 int condCount = 0;
513
518
520 int roundCount = 0;
521 std::vector<int> htmlDetailsStack;
522
523 bool insideParBlock = false;
524 bool inInternalDocs = false;
527 bool markdownSupport = true;
528
530
533 bool htmlAnchor = false;
534 bool CScode = false;
537};
538
539
540static std::mutex g_sectionMutex;
541static std::mutex g_formulaMutex;
542static std::mutex g_citeMutex;
543
544//-----------------------------------------------------------------------------
545
546static DString stripQuotes(const char *s);
547static SectionType sectionLevelToType(int level);
548static void stripTrailingWhiteSpace(DString &s);
549
550static void initParser(yyscan_t yyscanner);
551static bool checkStructuralIndicator(yyscan_t yyscanner);
552[[maybe_unused]] static bool makeStructuralIndicator(yyscan_t yyscanner,MakeEntryType maker);
553static void lineCount(yyscan_t yyscanner);
554static void addRequirementId(yyscan_t yyscanner);
555static void addXRefItem(yyscan_t yyscanner,
556 const DString &listName,const DString &itemTitle,
557 const DString &listTitle,bool append);
558static DString addFormula(yyscan_t yyscanner);
559static void checkFormula(yyscan_t yyscanner);
560static void addSection(yyscan_t yyscanner, bool addYYtext = true);
561static inline void setOutput(yyscan_t yyscanner,OutputContext ctx);
562static void addAnchor(yyscan_t yyscanner,const DString &anchor, const DString &title="");
563static inline void addOutput(yyscan_t yyscanner,const char *s);
564static inline void addOutput(yyscan_t yyscanner,const DString &s);
565static inline void addOutput(yyscan_t yyscanner,char c);
566static void endBrief(yyscan_t yyscanner);
567static void handleGuard(yyscan_t yyscanner,const DString &expr);
568static int yyread(yyscan_t yyscanner,char *buf,int max_size);
569static void addCite(yyscan_t yyscanner);
570static void addIline(yyscan_t yyscanner,int lineNr);
571static void addIlineBreak(yyscan_t yyscanner,int lineNr);
572static void escapeLabel(DString &label);
573
574#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0)
575
576//-----------------------------------------------------------------------------
577
578#undef YY_INPUT
579#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
580
581// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
582static inline const char *getLexerFILE() {return __FILE__;}
583#include "doxygen_lex.h"
584
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:89
Represents an unstructured piece of information, about an entity found in the sources.
Definition entry.h:117
constexpr EntryType(int t) noexcept
Definition types.h:904
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
Abstract interface for outline parsers.
Definition parserintf.h:42
Interface for the comment block scanner.
std::stack< GuardedSection > GuardedSectionStack
Definition commentscan.h:48
static bool handleShowInlineSource(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleMainpage(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleProtocol(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHeaderFile(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleDir(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleRelated(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleName(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleRaiseWarning(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleInheritanceGraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleStatic(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCopyBrief(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCopyDetails(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePublicSection(yyscan_t yyscanner, const DString &s, const StringVector &)
static bool handleIPrefix(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleExample(yyscan_t yyscanner, const DString &, const StringVector &)
SectionHandling
@ Escape
command is not-allowed in section title, it will be escaped
@ Replace
command will be handled in here / needs special handling here
@ Allowed
command is allowed without restrictions in section title
@ Break
command is not-allowed in section title, it will end the section title
static bool handleIFile(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePrivateSection(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleIfNot(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleGroupgraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleImage(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCategory(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideInheritanceGraph(yyscan_t yyscanner, const DString &, const StringVector &)
static void addCite(yyscan_t yyscanner)
static bool handleHideIncludedBygraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePackage(yyscan_t yyscanner, const DString &, const StringVector &)
XRefKind
@ XRef_Item
@ XRef_Deprecated
@ XRef_Todo
@ XRef_Test
@ XRef_Bug
@ XRef_None
static bool handleEndParBlock(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleSection(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePure(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePage(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleNamespace(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleIf(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideCallgraph(yyscan_t yyscanner, const DString &, const StringVector &)
static void setOutput(yyscan_t yyscanner, OutputContext ctx)
static bool handleHideReferencedByRelation(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideInlineSource(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideInitializer(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleAnchor(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleIncludedBygraph(yyscan_t yyscanner, const DString &, const StringVector &)
EntryType(*) MakeEntryType()
static void initParser(yyscan_t yyscanner)
static bool handleHideGroupgraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool makeStructuralIndicator(yyscan_t yyscanner, MakeEntryType maker)
static bool handleWeakGroup(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleMermaidFile(yyscan_t yyscanner, const DString &s, const StringVector &)
static bool handleReferencedByRelation(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCopyDoc(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleProtectedSection(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleEndIf(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleShowEnumValues(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCallergraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleEnum(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleFileInfoResult(yyscan_t yyscanner, const DString &, const StringVector &optList, bool isSection)
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
static bool handleHideDirectoryGraph(yyscan_t yyscanner, const DString &, const StringVector &)
static const char * stateToString(int state)
static bool handleFormatBlock(yyscan_t yyscanner, const DString &, const StringVector &)
static void escapeLabel(DString &label)
static bool handleAddToGroup(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleRetval(yyscan_t yyscanner, const DString &, const StringVector &)
static SectionType sectionLevelToType(int level)
static bool handleClass(yyscan_t yyscanner, const DString &, const StringVector &)
static std::mutex g_formulaMutex
static bool handleDirectoryGraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCollaborationgraph(yyscan_t yyscanner, const DString &, const StringVector &)
static void addRequirementId(yyscan_t yyscanner)
static bool handleHideCollaborationgraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleVerifies(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleInherit(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleDeprecated(yyscan_t yyscanner, const DString &, const StringVector &)
GuardType
@ Guard_If
@ Guard_ElseIf
@ Guard_IfNot
static bool handleLineInfo(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleReferencesRelation(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleInterface(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleQualifier(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleILine(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleStruct(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleParam(yyscan_t yyscanner, const DString &, const StringVector &)
static std::mutex g_citeMutex
static bool handleTodo(yyscan_t yyscanner, const DString &, const StringVector &)
static bool checkStructuralIndicator(yyscan_t yyscanner)
static std::mutex g_sectionMutex
static bool handleRelatedAlso(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleInternal(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleBug(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleAddIndex(yyscan_t yyscanner, const DString &, const StringVector &)
static void addOutput(yyscan_t yyscanner, const char *s)
static void handleGuard(yyscan_t yyscanner, const DString &expr)
static bool handleConcept(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleNoSubGrouping(yyscan_t yyscanner, const DString &, const StringVector &)
std::vector< HtmlContextInfo > HtmlContextStack
static DString fileInfoLookup(const FileInfo &fi, const std::string &name)
static bool handleModule(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCite(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleXRefItem(yyscan_t yyscanner, const DString &, const StringVector &)
static void endBrief(yyscan_t yyscanner)
CommandSpacing
@ Inline
command appears inline in the output which can be a brief description.
@ XRef
command is a cross reference (todo, bug, test, deprecated, xrefitem).
@ Invisible
command sets some property but does not appear in the output.
@ Block
command starts a new paragraphs / ends a brief description.
static bool handleBrief(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleShowInitializer(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleNoop(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleMemberOf(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleExtends(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleTest(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleIngroup(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleIRaise(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleIncludegraph(yyscan_t yyscanner, const DString &, const StringVector &)
static DString addFormula(yyscan_t yyscanner)
static const char * getLexerFILE()
OutputContext
@ OutputXRef
@ OutputDoc
@ OutputBrief
@ OutputInbody
static void addAnchor(yyscan_t yyscanner, const DString &anchor, const DString &title="")
static bool handleHideReferencesRelation(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePrivate(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleParBlock(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleElse(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideIncludegraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleCallgraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleSatisfies(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleRefItem(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleElseIf(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleToc(yyscan_t yyscanner, const DString &s, const StringVector &)
static void stripTrailingWhiteSpace(DString &s)
static bool handleFn(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleFile(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handlePublic(yyscan_t yyscanner, const DString &s, const StringVector &)
static DString stripQuotes(const char *s)
static bool handleDetails(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideEnumValues(yyscan_t yyscanner, const DString &, const StringVector &)
static void addXRefItem(yyscan_t yyscanner, const DString &listName, const DString &itemTitle, const DString &listTitle, bool append)
static bool handleFileInfoSection(yyscan_t yyscanner, const DString &cmdName, const StringVector &optList)
static bool handleIdlException(yyscan_t yyscanner, const DString &, const StringVector &)
bool(*) DocCmdFunc(yyscan_t yyscanner, const DString &name, const StringVector &optList)
static void addIline(yyscan_t yyscanner, int lineNr)
static void addIlineBreak(yyscan_t yyscanner, int lineNr)
static bool handleSubpage(yyscan_t yyscanner, const DString &s, const StringVector &)
static bool handleDef(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleHideCallergraph(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleDefGroup(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleProtected(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleUnion(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleOverload(yyscan_t yyscanner, const DString &, const StringVector &)
static void addSection(yyscan_t yyscanner, bool addYYtext=true)
static const std::unordered_map< std::string, DocCmdMap > docCmdMap
static bool handleRequirement(yyscan_t yyscanner, const DString &, const StringVector &)
static bool handleFileInfo(yyscan_t yyscanner, const DString &cmdName, const StringVector &optList)
static void checkFormula(yyscan_t yyscanner)
std::vector< std::string > StringVector
Definition containers.h:33
#define lineCount(s, len)
Some helper functions for std::string.
CommandSpacing spacing
DocCmdMap(DocCmdFunc h, CommandSpacing s, SectionHandling sh)
SectionHandling sectionHandling
DocCmdFunc handler
OutputContext context
HtmlContextInfo(const DString &tn, OutputContext ctx)
OutlineParserInterface * langParser
std::vector< int > htmlDetailsStack
HtmlContextStack htmlContextStack
OutputContext inContext
MakeEntryType currentMakeEntryType
DString * pOutputString
GuardedSectionStack * guards
Protection protection
Protection
Definition types.h:32
A bunch of utility functions.
585%}
586
587 /* start command character */
588CMD ("\\"|"@")
589PRE ("pre"|"PRE")
590TABLE ("table"|"TABLE")
591TABLEDEL ("table"|"tr"|"th"|"td"|"TABLE"|"TR"|"TH"|"TD")
592P [pP]
593UL ("ul"|"UL")
594OL ("ol"|"OL")
595DL ("dl"|"DL")
596IMG ("img"|"IMG")
597HR ("hr"|"HR")
598PARA ("para"|"PARA")
599CODE ("code"|"CODE")
600ENDCODE "/"{CODE}
601CAPTION ("caption"|"CAPTION")
602CENTER ("center"|"CENTER")
603DIV ("div"|"DIV")
604DETAILS ("details"|"DETAILS")
605BLOCKQUOTE ("blockquote"|"BLOCKQUOTE")
606DETAILEDHTML {CENTER}|{DIV}|{PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA}|{BLOCKQUOTE}
607DETAILEDHTMLOPT {CODE}
608DETAILEDHTMLOPTEND {ENDCODE}
609SUMMARY ("summary"|"SUMMARY")
610REMARKS ("remarks"|"REMARKS")
611AHTML [aA]{BN}*
612ANCHTML ("id"|"name"|"ID"|"NAME")"="("\""{LABELID}"\""|"'"{LABELID}"'"|{LABELID})
613BN [ \t\n\r]
614B [ \t]
615Bopt {B}*
616ATTR ({B}+[^>\n]*)?
617DOCNL "\n"|"\\ilinebr"
618LC "\\"{B}*"\n"
619NW [^a-z_A-Z0-9]
620FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+=@&#~]
621FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+=@&#~]
622FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"")
623ID [$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*
624LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
625REQID [a-z_A-Z0-9\x80-\xFF\-]+
626CITESCHAR [a-z_A-Z0-9\x80-\xFF\-\?]
627CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?]*
628CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\""
629SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
630SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
631TMPLSPEC "<"{BN}*[^>]+{BN}*">"
632MAILADDR ("mailto:")?[a-z_A-Z0-9\x80-\xff.+-]+"@"[a-z_A-Z0-9\x80-\xff-]+("."[a-z_A-Z0-9\x80-\xff\-]+)+[a-z_A-Z0-9\x80-\xff\-]+
633RCSTAG "$"{ID}":"[^\n$]+"$"
634MODULE_ID ({ID}".")*{ID}
635LINENR {Bopt}[1-9][0-9]*
636IFILELINE ("\\ifile \""[^"]*"\" \\iline "[0-9]+" "("iprefix \""[^"]*"\" ")?("iraise "[0-9]+" ")?)
637DOXYCFG [A-Z][A-Z_0-9]*
638
639 // C start comment
640CCS "/\*"
641 // C end comment
642CCE "*\/"
643
644 // end of section title with asterisk
645STAopt [^\n@\\*]*
646 // end of section title without asterisk
647STopt [^\n@\\‍]*
648
649%option noyywrap
650
651 /* comment parsing states. */
652%x Comment
653%x PageDocArg1
654%x PageDocArg2
655%x RelatesParam1
656%x ClassDocArg1
657%x ClassDocArg2
658%x ClassDocArg3
659%x CategoryDocArg1
660%x XRefItemParam1
661%x XRefItemParam2
662%x XRefItemParam3
663%x FileDocArg1
664%x ParamArg1
665%x EnumDocArg1
666%x NameSpaceDocArg1
667%x PackageDocArg1
668%x ConceptDocArg1
669%x ModuleDocArg1
670%x GroupDocArg1
671%x GroupDocArg2
672%x SectionLabel
673%x SectionTitle
674%x SubpageLabel
675%x SubpageTitle
676%x SatisfiesLabel
677%x SatisfiesTitle
678%x VerifiesLabel
679%x VerifiesTitle
680%x RequirementLabel
681%x RequirementTitle
682%x FormatBlock
683%x LineParam
684%x GuardParam
685%x GuardParamEnd
686%x SkipGuardedSection
687%x SkipInternal
688%x NameParam
689%x InGroupParam
690%x FnParam
691%x OverloadParam
692%x InheritParam
693%x ExtendsParam
694%x ReadFormulaShort
695%x ReadFormulaShortSection
696%x ReadFormulaRound
697%x ReadFormulaRoundSection
698%x ReadFormulaLong
699%x AnchorLabel
700%x AnchorLabelSection
701%x HtmlComment
702%x HtmlA
703%x SkipLang
704%x CiteLabel
705%x CiteLabelSection
706%x CopyDoc
707%x GuardExpr
708%x CdataSection
709%x Noop
710%x RaiseWarning
711%x RaiseWarningSection
712%x Qualifier
713%x LinkSection
714%x IFile
715%x IFileSection
716%x ILine
717%x ILineSection
718%x IRaise
719%x IRaisePrefix
720
722
723 /* What can happen in while parsing a comment block:
724 * commands (e.g. @page, or \page)
725 * escaped commands (e.g. @@page or \\page).
726 * formulas (e.g. \f$...\f$ \f[...\f] \f{...\f} \f(...\f) )
727 * directories (e.g. \doxygen\src\‍)
728 * autolist end. (e.g. a dot on an otherwise empty line)
729 * newlines.
730 * end of brief description due to blank line.
731 * end of brief description due to some command (@command, or <command>).
732 * words and whitespace and other characters (#,?!, etc).
733 * grouping commands (e.g. @{ and @})
734 * language switch (e.g. \~english or \~).
735 * mail address (e.g. doxygen@gmail.com).
736 * quoted text, such as "foo@bar"
737 * XML commands, <summary></summary><remarks></remarks>
738 */
739
740<Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command
741 addOutput(yyscanner,yytext);
742 }
743<Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command
744 addOutput(yyscanner,yytext);
745 }
746<Comment>{MAILADDR} { // mail address
747 addOutput(yyscanner,yytext);
748 }
749<Comment>"\""[^"\n]*"\"" { // quoted text
750 addOutput(yyscanner,yytext);
751 }
752<Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!)
753 addOutput(yyscanner,yytext);
754 }
755<Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description
756 DString htmlOpenTag(yytext);
757 size_t spacePos = htmlOpenTag.find(' '); // check for optional attributes
758 if (spacePos==DString::npos) spacePos=yyleng-1;
759 DString htmlTagName = htmlOpenTag.mid(1,spacePos-1);
760 //printf("found open tag '%s'\n",qPrint(htmlTagName));
761 yyextra->htmlContextStack.emplace_back(htmlTagName,yyextra->inContext);
762 if (yyextra->inContext==OutputBrief)
763 {
764 setOutput(yyscanner,OutputDoc);
765 }
766 // continue with the same input
767 REJECT;
768 }
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:323
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:183
769<Comment>"</"{DETAILEDHTML}">" { // HTML command that ends a brief description
770 DString htmlCloseTag(yytext);
771 DString htmlTagName = htmlCloseTag.mid(2,htmlCloseTag.length()-3);
772 //printf("found close tag '%s'\n",qPrint(htmlTagName));
773 if (!yyextra->htmlContextStack.empty() &&
774 yyextra->htmlContextStack.back().tagName==htmlTagName)
775 {
776 if (yyextra->inContext==OutputXRef && yyextra->htmlContextStack.back().context!=OutputXRef)
777 {
778 //printf("switching back to OutputDoc\n");
779 setOutput(yyscanner,OutputDoc);
780 }
781 yyextra->htmlContextStack.pop_back();
782 }
783 REJECT;
784 }
785<Comment>"<"{DETAILEDHTMLOPT}">" { // HTML <code> command that ends a brief description
786 // without attributes
787 if (yyextra->current->lang==SrcLangExt::CSharp)
788 {
789 yyextra->CScode=true;
790 setOutput(yyscanner,OutputDoc);
791 addOutput(yyscanner,"@code{cs}");
792 }
793 else
794 {
795 // continue with the same input
796 REJECT;
797 }
798 }
799<Comment>"<"{DETAILEDHTMLOPTEND}">" { // HTML command that ends a brief description
800 if (yyextra->CScode)
801 {
802 addOutput(yyscanner,"@endcode");
803 yyextra->CScode=false;
804 }
805 else
806 {
807 yyextra->CScode=false;
808 // continue with the same input
809 REJECT;
810 }
811 }
812<Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML <code> command that ends a brief description
813 // with attributes, so cannot be CS.
814 if (yyextra->current->lang==SrcLangExt::CSharp)
815 {
816 setOutput(yyscanner,OutputDoc);
817 }
818 // continue with the same input
819 REJECT;
820 }
821<Comment>"<"{DETAILS}{ATTR}">" { // start of a HTML style details description
822 yyextra->htmlDetailsStack.push_back(0);
823 yyextra->htmlContextStack.emplace_back("details",yyextra->inContext);
824 if (yyextra->inContext==OutputBrief)
825 {
826 setOutput(yyscanner,OutputDoc);
827 }
828 addOutput(yyscanner,yytext);
829 }
830<Comment>"</"{DETAILS}">" { // end of a HTML style details description
831 if (!yyextra->htmlDetailsStack.empty())
832 {
833 yyextra->htmlDetailsStack.pop_back();
834 }
835 if (!yyextra->htmlContextStack.empty() &&
836 yyextra->htmlContextStack.back().tagName=="details")
837 {
838 if (yyextra->inContext==OutputXRef && yyextra->htmlContextStack.back().context!=OutputXRef)
839 {
840 //printf("switching back to OutputDoc\n");
841 setOutput(yyscanner,OutputDoc);
842 }
843 yyextra->htmlContextStack.pop_back();
844 }
845 addOutput(yyscanner,yytext);
846 }
847<Comment>"<"{AHTML} { // potential start of HTML anchor, see issue 9200
848 yyextra->htmlAnchorStr = yytext;
849 yyextra->htmlAnchor = false;
850 BEGIN(HtmlA);
851 }
852<HtmlA>{ANCHTML} { // only labels that can be converted to doxygen anchor
853 yyextra->htmlAnchorStr += yytext;
854 DString tag(yytext);
855 size_t s=tag.find("=");
856 char c=tag[s+1];
857 DString id;
858 if (c=='\'' || c=='"') // valid start
859 {
860 size_t e=tag.find(c,s+2);
861 if (e!=DString::npos) // found matching end
862 {
863 id=tag.mid(s+2,e-s-2); // extract id
864 addAnchor(yyscanner,id);
865 }
866 }
867 else
868 {
869 id=tag.mid(s+1);
870 addAnchor(yyscanner,id);
871 }
872 if (!id.empty() && !yyextra->htmlAnchor)
873 {
874 // only use first analogous to what is in docparser
875 addOutput(yyscanner,"@anchor ");
876 addOutput(yyscanner,id.data());
877 addOutput(yyscanner," ");
878 yyextra->htmlAnchor = true;
879 }
880 }
881<HtmlA>("\""[^\n\"]*"\""|"'"[^\n']*"'") {
882 yyextra->htmlAnchorStr += yytext;
883 }
884<HtmlA>">"|"/>" {
885 if (!yyextra->htmlAnchor)
886 {
887 addOutput(yyscanner,yyextra->htmlAnchorStr);
888 addOutput(yyscanner,yytext);
889 }
890 else
891 {
892 if (yyleng == 1) // to keep <a></a> pairs, otherwise single </a> present
893 {
894 addOutput(yyscanner,"<a>");
895 }
896 }
897 BEGIN(Comment);
898 }
899<HtmlA>{DOCNL} { // newline
900 yyextra->htmlAnchorStr += yytext;
901 if (*yytext == '\n') yyextra->lineNr++;
902 }
903<HtmlA>. { // catch-all for anything else
904 yyextra->htmlAnchorStr += yytext;
905 }
906<Comment>"<"{SUMMARY}">" { // start of a .NET XML style brief description
907 if (yyextra->htmlDetailsStack.empty())
908 {
909 setOutput(yyscanner,OutputBrief);
910 }
911 else // HTML5 style <summary> as part of <details> section.
912 {
913 addOutput(yyscanner,yytext);
914 }
915 }
916<Comment>"<"{REMARKS}">" { // start of a .NET XML style detailed description
917 setOutput(yyscanner,OutputDoc);
918 addOutput(yyscanner,yytext);
919 }
920<Comment>"</"{SUMMARY}">" { // start of a .NET XML style detailed description
921 if (!yyextra->htmlDetailsStack.empty())
922 {
923 addOutput(yyscanner,yytext);
924 }
925 else
926 {
927 setOutput(yyscanner,OutputDoc);
928 }
929 }
930<Comment>"</"{REMARKS}">" { // end of a brief or detailed description
931 setOutput(yyscanner,OutputDoc);
932 addOutput(yyscanner,yytext);
933 }
934<Comment>"<"{CAPTION}{ATTR}">" {
935 DString tag(yytext);
936 size_t s=tag.find("id=");
937 if (s!=DString::npos) // command has id attribute
938 {
939 char c=tag[s+3];
940 if (c=='\'' || c=='"') // valid start
941 {
942 size_t e=tag.find(c,s+4);
943 if (e!=DString::npos) // found matching end
944 {
945 DString id=tag.mid(s+4,e-s-4); // extract id
946 addAnchor(yyscanner,id);
947 }
948 }
949 }
950 addOutput(yyscanner,yytext);
951 }
952<Comment>"<"{PRE}{ATTR}">" {
953 yyextra->insidePre=true;
954 addOutput(yyscanner,yytext);
955 }
956<Comment>"</"{PRE}">" {
957 yyextra->insidePre=false;
958 addOutput(yyscanner,yytext);
959 }
960<Comment>{RCSTAG} { // RCS tag which end a brief description
961 setOutput(yyscanner,OutputDoc);
962 REJECT;
963 }
964<Comment>"<!--" {
965 BEGIN(HtmlComment);
966 }
967<Comment>"<!\‍[CDATA\‍[" {
968 BEGIN(CdataSection);
969 }
970<Comment>{B}*{CMD}"endinternal"{B}* {
971 addOutput(yyscanner," \\endinternal ");
972 if (!yyextra->inInternalDocs)
973 warn(yyextra->fileName,yyextra->lineNr,
974 "found \\endinternal without matching \\internal"
975 );
976 yyextra->inInternalDocs = false;
977 }
#define warn(file, line, fmt,...)
Definition message.h:97
978<Comment>{B}*"\\ilinebr "{B}* { // preserve spacing around \\ilinebr
979 addOutput(yyscanner,yytext);
980 }
981<Comment>(\n|"\\ilinebr ")/({B}*(\n|{IFILELINE}?"\\ilinebr "))+ { // at least one blank line (or blank line command)
982 if (yyextra->inContext==OutputBrief)
983 {
984 endBrief(yyscanner);
985 }
986 else
987 {
988 REJECT;
989 }
990 }
991<Comment>{B}*{CMD}[a-z_A-Z]+"{"[^}]*"}"{B}* |
992<Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command
993 // the {B}* in the front was added for bug620924
994 DString fullMatch = yytext;
995 size_t idx = fullMatch.find('{');
996 /* handle `f{` command as special case */
997 if ((idx > 1) && (yytext[idx-1] == 'f') && (yytext[idx-2] == '\\' || yytext[idx-2] =='@')) REJECT;
998 size_t idxEnd = fullMatch.find('}',idx+1);
999 DString cmdName;
1000 StringVector optList;
1001 if (idx == DString::npos) // no options
1002 {
1003 cmdName = fullMatch.stripWhiteSpace().mid(1); // to remove {CMD}
1004 }
1005 else // options present
1006 {
1007 cmdName = fullMatch.left(idx).stripWhiteSpace().mid(1); // to remove {CMD}
1008 DString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace();
1009 optList = split(optStr.str(),",");
1010 }
1011 auto it = docCmdMap.find(cmdName.str());
1012 //printf("lookup command '%s' found=%d\n",qPrint(cmdName),it!=docCmdMap.end());
1013 if (it!=docCmdMap.end()) // special action is required
1014 {
1015 int i=0;
1016 while (yytext[i]==' ' || yytext[i]=='\t') i++;
1017 yyextra->spaceBeforeCmd = fullMatch.left(i);
1018 CommandSpacing spacing = it->second.spacing;
1019 if ((spacing==CommandSpacing::Block || spacing==CommandSpacing::XRef) &&
1020 !(yyextra->inContext==OutputXRef && cmdName=="parblock"))
1021 {
1022 yyextra->briefEndsAtDot=false;
1023 bool insideXRef = yyextra->inContext==OutputXRef && spacing==CommandSpacing::XRef;
1024 // this command forces the end of brief description
1025 setOutput(yyscanner,insideXRef ? OutputXRef : OutputDoc);
1026 }
1027 //if (i>0) addOutput(yyscanner,DString(yytext).left(i)); // removed for bug 689341
1028 if (it->second.handler && it->second.handler(yyscanner, cmdName, optList))
1029 {
1030 // implicit split of the comment block into two
1031 // entries. Restart the next block at the start
1032 // of this command.
1033 yyextra->parseMore=true;
1034
1035 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);
1036 yyterminate();
1037 }
1038 else if (it->second.handler==nullptr)
1039 {
1040 // command without handler, to be processed
1041 // later by parsedoc.cpp
1042 addOutput(yyscanner,yytext);
1043 }
1044 }
1045 else // command not relevant
1046 {
1047 addOutput(yyscanner,yytext);
1048 }
1049 }
size_t find(char c, size_t pos=0) const
Definition dstring.h:244
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:342
DString left(size_t len) const
Definition dstring.h:311
const std::string & str() const
Definition dstring.h:634
#define yyterminate()
StringVector split(const std::string &s, const std::string &delimiter)
split input string s by string delimiter delimiter.
Definition stringutil.h:117
1050<Comment>{B}*({CMD}{CMD})"f"[$\‍[{] { // escaped formula command
1051 addOutput(yyscanner,yytext);
1052 }
1053<Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command
1054 DString langId = DString(yytext).stripWhiteSpace().mid(2);
1055 if (!langId.empty() &&
1056 dstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE),langId)!=0)
1057 { // enable language specific section
1058 if (!Config_isAvailableEnum(OUTPUT_LANGUAGE,langId))
1059 {
1060 warn(yyextra->fileName,yyextra->lineNr,
1061 "non supported language '{}' specified in '{}'",langId,DString(yytext).stripWhiteSpace());
1062 }
1063 BEGIN(SkipLang);
1064 }
1065 }
DString()=default
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:153
#define Config_getEnumAsString(name)
Definition config.h:36
#define Config_isAvailableEnum(name, value)
Definition config.h:45
int dstricmp(const char *s1, const char *s2)
Definition dstring.cpp:439
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
Definition stringutil.h:75
1066<Comment>{B}*{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment
1067 setOutput(yyscanner,OutputDoc);
1068 yyextra->formulaText="";
1069 yyextra->formulaPreText="\\begin";
1070 yyextra->formulaPostText="";
1071 yyextra->formulaEnv=DString(yytext).stripWhiteSpace().mid(2);
1072 if (yyextra->formulaEnv.at(yyextra->formulaEnv.length()-1)=='{')
1073 {
1074 // remove trailing open brace
1075 yyextra->formulaEnv=yyextra->formulaEnv.left(yyextra->formulaEnv.length()-1);
1076 }
1077 yyextra->formulaPreText+=yyextra->formulaEnv;
1078 yyextra->formulaNewLines=0;
1079 BEGIN(ReadFormulaLong);
1080 }
1081<Comment>{B}*{CMD}"f$" { // start of a inline formula
1082 yyextra->formulaText="";
1083 yyextra->formulaPreText="$";
1084 yyextra->formulaPostText="";
1085 yyextra->formulaNewLines=0;
1086 BEGIN(ReadFormulaShort);
1087 }
1088<Comment>{B}*{CMD}"f(" { // start of a inline formula
1089 yyextra->formulaText="";
1090 yyextra->formulaPreText="";
1091 yyextra->formulaPostText="";
1092 yyextra->formulaNewLines=0;
1093 BEGIN(ReadFormulaRound);
1094 }
1095<Comment>{B}*{CMD}"f[" { // start of a block formula
1096 setOutput(yyscanner,OutputDoc);
1097 yyextra->formulaText="";
1098 yyextra->formulaPreText="\\[";
1099 yyextra->formulaPostText="";
1100 yyextra->formulaNewLines=0;
1101 BEGIN(ReadFormulaLong);
1102 }
1103<Comment>{B}*{CMD}"{" { // begin of a group
1104 //yyextra->langParser->handleGroupStartCommand(yyextra->memberGroupHeader);
1105 yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr);
1106 }
1107<Comment>{B}*{CMD}"}" { // end of a group
1108 //yyextra->langParser->handleGroupEndCommand();
1109 yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,true);
1110 yyextra->docGroup.clearHeader();
1111 yyextra->parseMore=true;
1112 yyextra->needNewEntry = true;
1113 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + (int)strlen(yytext);
1114 yyterminate();
1115 }
1116<Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character
1117 addOutput(yyscanner,yytext);
1118 }
1119<Comment>[a-z_A-Z]+ { // normal word
1120 addOutput(yyscanner,yytext);
1121 }
1122<Comment>^{B}*"."{Bopt}/\n { // explicit end autolist: e.g " ."
1123 addOutput(yyscanner,yytext);
1124 }
1125<Comment>^{B}*[1-9][0-9]*"."{B}+ |
1126<Comment>^{B}*[*+]{B}+ { // start of autolist
1127 if (!yyextra->markdownSupport)
1128 {
1129 REJECT;
1130 }
1131 else
1132 {
1133 if (yyextra->inContext!=OutputXRef)
1134 {
1135 yyextra->briefEndsAtDot=false;
1136 setOutput(yyscanner,OutputDoc);
1137 }
1138 addOutput(yyscanner,yytext);
1139 }
1140 }
1141<Comment>^{B}*"-"{B}+ { // start of autolist
1142 if (yyextra->inContext!=OutputXRef)
1143 {
1144 yyextra->briefEndsAtDot=false;
1145 setOutput(yyscanner,OutputDoc);
1146 }
1147 addOutput(yyscanner,yytext);
1148 }
1149<Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{Bopt}/\n { // horizontal line (dashed)
1150 addOutput(yyscanner,yytext);
1151 }
1152<Comment>{CMD}"---" { // escaped mdash
1153 addOutput(yyscanner,yytext);
1154 }
1155<Comment>{CMD}"--" { // escaped ndash
1156 addOutput(yyscanner,yytext);
1157 }
1158<Comment>"---" { // mdash
1159 addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "&mdash;");
1160 }
1161<Comment>"--" { // ndash
1162 addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "&ndash;");
1163 }
1164<Comment>"-#"{B}+ { // numbered item
1165 if (yyextra->inContext!=OutputXRef)
1166 {
1167 yyextra->briefEndsAtDot=false;
1168 setOutput(yyscanner,OutputDoc);
1169 }
1170 addOutput(yyscanner,yytext);
1171 }
1172<Comment>[?!][a-z_A-Z0-9\‍(\‍)=<] |
1173<Comment>("."+)[a-z_A-Z0-9\‍)] { // . at start or in the middle of a word, or ellipsis
1174 // ? or ! in middle of word or followed by equal sign or round bracket.
1175 addOutput(yyscanner,yytext);
1176 }
1177<Comment>{CMD}[\.?!] { // we have to be a bit careful with the special commands
1178 // \. \? and \! as they might otherwise terminate a brief description
1179 addOutput(yyscanner,yytext);
1180 }
1181<Comment>".\\"[ \t] { // . with escaped space.
1182 addOutput(yyscanner,yytext[0]);
1183 addOutput(yyscanner,yytext[2]);
1184 }
1185<Comment>"."[,:;] { // . with some puntuations such as "e.g.," or "e.g.:"
1186 addOutput(yyscanner,yytext);
1187 }
1188<Comment>"...\\"[ \t] { // ellipsis with escaped space.
1189 addOutput(yyscanner,"... ");
1190 }
1191<Comment>"..."/[^\.] { // ellipsis
1192 addOutput(yyscanner,"...");
1193 }
1194<Comment>".."[\.]?/[^ \t\n] { // internal ellipsis
1195 addOutput(yyscanner,yytext);
1196 }
1197<Comment>(\n|"\\ilinebr ")({B}*(\n|"\\ilinebr "))+ { // at least one blank line (or blank line command)
1198 if (yyextra->inContext==OutputXRef)
1199 {
1200 // see bug 613024, we need to put the newlines after ending the XRef section.
1201 if (!yyextra->insideParBlock) setOutput(yyscanner,OutputDoc);
1202 yy_size_t i;
1203 for (i=0;i<(yy_size_t)yyleng;)
1204 {
1205 if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++;
1206 else if (strncmp(yytext+i,"\\ilinebr ",9)==0) addOutput(yyscanner,"\\ilinebr "),i+=9;
1207 else i++;
1208 }
1209 }
1210 else if (yyextra->inContext!=OutputBrief)
1211 {
1212 yy_size_t i;
1213 for (i=0;i<(yy_size_t)yyleng;)
1214 {
1215 if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++;
1216 else if (strncmp(yytext+i,"\\ilinebr ",9)==0) addOutput(yyscanner,"\\ilinebr "),i+=9;
1217 else i++;
1218 }
1219 setOutput(yyscanner,OutputDoc);
1220 }
1221 else // yyextra->inContext==OutputBrief
1222 { // only go to the detailed description if we have
1223 // found some brief description and not just whitespace
1224 endBrief(yyscanner);
1225 }
1226 lineCount(yyscanner);
1227 }
1228<Comment>"."[?!] |
1229<Comment>[\.?!] { // potential end of a JavaDoc style comment
1230 addOutput(yyscanner,yytext);
1231 if (yyextra->briefEndsAtDot)
1232 {
1233 setOutput(yyscanner,OutputDoc);
1234 yyextra->briefEndsAtDot=false;
1235 }
1236 }
1237<Comment>{DOCNL} { // newline
1238 addOutput(yyscanner,yytext);
1239 if (*yytext == '\n') yyextra->lineNr++;
1240 }
1241<Comment>"<"[/]?{TABLEDEL}">" { // In case in xrefitem type some special handling is required
1242 if (yyextra->inContext==OutputXRef)
1243 {
1244 setOutput(yyscanner,OutputDoc);
1245 addOutput(yyscanner,yytext);
1246 }
1247 else
1248 {
1249 REJECT;
1250 }
1251 }
1252<Comment>. { // catch-all for anything else
1253 addOutput(yyscanner,*yytext);
1254 }
1255
1256
1257 /* -------------- Rules for handling HTML comments ----------- */
1258
1259<HtmlComment>"---"[!]?">"{B}* {
1260 warn(yyextra->fileName,yyextra->lineNr,
1261 "incorrect HTML end comment --->"
1262 );
1263 }
1264<HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); }
1265<HtmlComment>{DOCNL} {
1266 if (*yytext=='\n')
1267 {
1268 yyextra->lineNr++;
1269 addOutput(yyscanner," \\iline "+DString().setNum(yyextra->lineNr)+" ");
1270 }
1271 }
1272<HtmlComment>[^\\\n\-]+ { // ignore unimportant characters
1273 }
1274<HtmlComment>. { // ignore every else
1275 }
1276
1277<CdataSection>"\‍]\‍]>" {
1278 BEGIN( Comment );
1279 }
1280<CdataSection>{DOCNL} {
1281 addOutput(yyscanner,'\n');
1282 if (*yytext=='\n') yyextra->lineNr++;
1283 }
1284<CdataSection>[<>&] { // the special XML characters for iwhich the CDATA section is especially used
1285 addOutput(yyscanner,'\\');
1286 addOutput(yyscanner,*yytext);
1287 }
1288<CdataSection>[^\\\n\‍]<>&]+ {
1289 addOutput(yyscanner,yytext);
1290 }
1291<CdataSection>. {
1292 addOutput(yyscanner,*yytext);
1293 }
1294
1295 /* -------------- Rules for handling formulas ---------------- */
1296
1297<ReadFormulaShort,ReadFormulaShortSection>{CMD}"f$" { // end of inline formula
1298 yyextra->formulaPostText+="$";
1299 DString form = addFormula(yyscanner);
1300 addOutput(yyscanner," "+form);
1301 if (YY_START == ReadFormulaShort)
1302 {
1303 BEGIN(Comment);
1304 }
1305 else
1306 {
1307 yyextra->sectionTitle+= " "+form;
1308 BEGIN(SectionTitle);
1309 }
1310 }
1311<ReadFormulaRound,ReadFormulaRoundSection>{CMD}"f)" { // end of inline formula
1312 DString form = addFormula(yyscanner);
1313 addOutput(yyscanner," "+form);
1314 if (YY_START == ReadFormulaRound)
1315 {
1316 BEGIN(Comment);
1317 }
1318 else
1319 {
1320 yyextra->sectionTitle+= " "+form;
1321 BEGIN(SectionTitle);
1322 }
1323 }
1324<ReadFormulaLong>{CMD}"f]" { // end of block formula
1325 yyextra->formulaPostText+="\\]";
1326 addOutput(yyscanner," "+addFormula(yyscanner));
1327 BEGIN(Comment);
1328 }
1329<ReadFormulaLong>{CMD}"f}" { // end of custom env formula
1330 yyextra->formulaPostText+="\\end";
1331 yyextra->formulaPostText+=yyextra->formulaEnv;
1332 addOutput(yyscanner," "+addFormula(yyscanner));
1333 BEGIN(Comment);
1334 }
1335<ReadFormulaLong,ReadFormulaShort,ReadFormulaShortSection,ReadFormulaRound,ReadFormulaRoundSection>[^\\@\n]+ { // any non-special character
1336 yyextra->formulaText+=yytext;
1337 }
1338<ReadFormulaLong,ReadFormulaShort,ReadFormulaShortSection,ReadFormulaRound,ReadFormulaRoundSection>\n { // new line
1339 yyextra->formulaNewLines++;
1340 yyextra->formulaText+=*yytext;
1341 yyextra->lineNr++;
1342 addIline(yyscanner,yyextra->lineNr);
1343 }
1344<ReadFormulaLong,ReadFormulaShort,ReadFormulaShortSection,ReadFormulaRound,ReadFormulaRoundSection>. { // any other character
1345 yyextra->formulaText+=*yytext;
1346 }
1347
1348 /* ------------ handle argument of enum command --------------- */
1349
1350<EnumDocArg1>{SCOPEID} { // handle argument
1351 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1352 yyextra->current->name = yytext;
1353 BEGIN( Comment );
1354 }
1355<EnumDocArg1>{LC} { // line continuation
1356 yyextra->lineNr++;
1357 addOutput(yyscanner,'\n');
1358 }
1359<EnumDocArg1>{DOCNL} { // missing argument
1360 warn(yyextra->fileName,yyextra->lineNr,
1361 "missing argument after '\\enum'."
1362 );
1363 unput_string(yytext,yyleng);
1364 BEGIN( Comment );
1365 }
#define unput_string(yytext, yyleng)
1366<EnumDocArg1>. { // ignore other stuff
1367 }
1368
1369 /* ------------ handle argument of namespace command --------------- */
1370
1371<NameSpaceDocArg1>{SCOPENAME} { // handle argument
1372 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1373 lineCount(yyscanner);
1374 yyextra->current->name = substitute(removeRedundantWhiteSpace(yytext),".","::");
1375 BEGIN( Comment );
1376 }
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:480
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:458
1377<NameSpaceDocArg1>{LC} { // line continuation
1378 yyextra->lineNr++;
1379 addOutput(yyscanner,'\n');
1380 }
1381<NameSpaceDocArg1>{DOCNL} { // missing argument
1382 warn(yyextra->fileName,yyextra->lineNr,
1383 "missing argument after '\\namespace'."
1384 );
1385 unput_string(yytext,yyleng);
1386 BEGIN( Comment );
1387 }
1388<NameSpaceDocArg1>. { // ignore other stuff
1389 }
1390
1391 /* ------------ handle argument of package command --------------- */
1392
1393<PackageDocArg1>{ID}("."{ID})* { // handle argument
1394 yyextra->current->name = yytext;
1395 BEGIN( Comment );
1396 }
1397<PackageDocArg1>{LC} { // line continuation
1398 yyextra->lineNr++;
1399 addOutput(yyscanner,'\n');
1400 }
1401<PackageDocArg1>{DOCNL} { // missing argument
1402 warn(yyextra->fileName,yyextra->lineNr,
1403 "missing argument after \\package."
1404 );
1405 unput_string(yytext,yyleng);
1406 //addOutput(yyscanner,'\n');
1407 //if (*yytext=='\n') yyextra->lineNr++;
1408 BEGIN( Comment );
1409 }
1410<PackageDocArg1>. { // ignore other stuff
1411 }
1412
1413 /* ------------ handle argument of concept command --------------- */
1414
1415<ConceptDocArg1>{SCOPEID} { // handle argument
1416 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1417 yyextra->current->name = yytext;
1418 BEGIN( Comment );
1419 }
1420<ConceptDocArg1>{LC} { // line continuation
1421 yyextra->lineNr++;
1422 addOutput(yyscanner,'\n');
1423 }
1424<ConceptDocArg1>{DOCNL} { // missing argument
1425 warn(yyextra->fileName,yyextra->lineNr,
1426 "missing argument after '\\concept'."
1427 );
1428 unput_string(yytext,yyleng);
1429 BEGIN( Comment );
1430 }
1431<ConceptDocArg1>. { // ignore other stuff
1432 }
1433
1434 /* ------------ handle argument of module command --------------- */
1435<ModuleDocArg1>{MODULE_ID} { // handle argument
1436 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1437 yyextra->current->name = yytext;
1438 BEGIN( Comment );
1439 }
1440<ModuleDocArg1>{LC} { // line continuation
1441 yyextra->lineNr++;
1442 addOutput(yyscanner,'\n');
1443 }
1444<ModuleDocArg1>{DOCNL} { // missing argument
1445 warn(yyextra->fileName,yyextra->lineNr,
1446 "missing argument after '\\module'."
1447 );
1448 unput_string(yytext,yyleng);
1449 BEGIN( Comment );
1450 }
1451<ModuleDocArg1>. { // ignore other stuff
1452 }
1453
1454 /* ------ handle argument of class/struct/union command --------------- */
1455
1456<ClassDocArg1>{SCOPENAME}{TMPLSPEC} {
1457 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1458 lineCount(yyscanner);
1459 yyextra->current->name = substitute(removeRedundantWhiteSpace(yytext),".","::");
1460 BEGIN( ClassDocArg2 );
1461 }
1462<ClassDocArg1>{SCOPENAME} { // first argument
1463 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1464 lineCount(yyscanner);
1465 yyextra->current->name = substitute(yytext,".","::");
1466 if (yyextra->current->section.isProtocolDoc())
1467 {
1468 yyextra->current->name+="-p";
1469 }
1470 // prepend outer scope name
1471 BEGIN( ClassDocArg2 );
1472 }
1473<CategoryDocArg1>{SCOPENAME}{B}*"("[^\‍)]+")" {
1474 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
1475 lineCount(yyscanner);
1476 yyextra->current->name = substitute(yytext,".","::");
1477 BEGIN( ClassDocArg2 );
1478 }
1479<ClassDocArg1,CategoryDocArg1>{LC} { // line continuation
1480 yyextra->lineNr++;
1481 addOutput(yyscanner,'\n');
1482 }
1483<ClassDocArg1,CategoryDocArg1>{DOCNL} {
1484 warn(yyextra->fileName,yyextra->lineNr,
1485 "missing argument after '\\{}'.",yyextra->currentCmd
1486 );
1487 unput_string(yytext,yyleng);
1488 BEGIN( Comment );
1489 }
1490<ClassDocArg1,CategoryDocArg1>. { // ignore other stuff
1491 }
1492
1493<ClassDocArg2>{DOCNL} {
1494 unput_string(yytext,yyleng);
1495 BEGIN( Comment );
1496 }
1497<ClassDocArg2>{FILE}|"<>" { // second argument; include file
1498 yyextra->current->includeFile = yytext;
1499 BEGIN( ClassDocArg3 );
1500 }
1501<ClassDocArg2>{LC} { // line continuation
1502 yyextra->lineNr++;
1503 addOutput(yyscanner,'\n');
1504 }
1505<ClassDocArg2>. { // ignore other stuff
1506 }
1507
1508<ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name
1509 yyextra->current->includeName = yytext;
1510 BEGIN( Comment );
1511 }
1512<ClassDocArg3>{LC} { // line continuation
1513 yyextra->lineNr++;
1514 addOutput(yyscanner,'\n');
1515 }
1516<ClassDocArg3>{DOCNL} {
1517 //if (*yytext=='\n') yyextra->lineNr++;
1518 unput_string(yytext,yyleng);
1519 BEGIN( Comment );
1520 }
1521<ClassDocArg3>. { // ignore other stuff
1522 }
1523
1524 /* --------- handle arguments of {def,add,weak}group commands --------- */
1525
1526<GroupDocArg1>{LABELID}(".html"|".xhtml")? { // group name
1527 yyextra->current->name = yytext;
1528 //lastDefGroup.groupname = yytext;
1529 //lastDefGroup.pri = yyextra->current->groupingPri();
1530 // the .html stuff is for Qt compatibility
1531 if (yyextra->current->name.endsWith(".html"))
1532 {
1533 yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-5);
1534 }
1535 else if (yyextra->current->name.endsWith(".xhtml"))
1536 {
1537 yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-6);
1538 }
1539 yyextra->current->type.clear();
1540 BEGIN(GroupDocArg2);
1541 }
1542<GroupDocArg1>"\\"{B}*"\n" { // line continuation
1543 yyextra->lineNr++;
1544 addOutput(yyscanner,'\n');
1545 }
1546<GroupDocArg1>{DOCNL} { // missing argument!
1547 warn(yyextra->fileName,yyextra->lineNr,
1548 "missing group name after {}",
1549 yyextra->current->groupDocCmd()
1550 );
1551 //addOutput(yyscanner,'\n');
1552 //if (*yytext=='\n') yyextra->lineNr++;
1553 unput_string(yytext,yyleng);
1554 BEGIN( Comment );
1555 }
1556<GroupDocArg1>. { // ignore other stuff
1557 }
1558<GroupDocArg2>"\\"{B}*"\n" { // line continuation
1559 yyextra->lineNr++;
1560 addOutput(yyscanner,'\n');
1561 }
1562<GroupDocArg2>[^\n\\‍]+ { // title (stored in type)
1563 yyextra->current->type += yytext;
1564 }
1565<GroupDocArg2>{DOCNL}+ {
1566 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
1567 if ( yyextra->current->groupDocType==Entry::GROUPDOC_NORMAL &&
1568 yyextra->current->type.empty()
1569 ) // defgroup requires second argument
1570 {
1571 warn(yyextra->fileName,yyextra->lineNr,
1572 "missing title after "
1573 "\\defgroup {}", yyextra->current->name
1574 );
1575 }
1576 unput_string(yytext,yyleng);
1577 int extraLineNr = 0;
1578 if (yyextra->inContext == OutputBrief)
1579 {
1580 for (int i = 0; i < yyleng; i++)
1581 {
1582 if (yytext[i]=='\n') extraLineNr++;
1583 }
1584 }
1585 //if (*yytext=='\n') yyextra->lineNr++;
1586 //addOutput(yyscanner,'\n');
1587 if ( yyextra->current->groupDocType!=Entry::GROUPDOC_NORMAL)
1588 {
1589 addOutput(yyscanner," \\ifile \""+ yyextra->fileName);
1590 addOutput(yyscanner,"\" \\iline " + DString().setNum(yyextra->lineNr + extraLineNr) + " \\ilinebr ");
1591 }
1592 BEGIN( Comment );
1593 }
@ GROUPDOC_NORMAL
defgroup
Definition entry.h:122
1594<GroupDocArg2>. { // title (stored in type)
1595 yyextra->current->type += yytext;
1596 }
1597
1598 /* --------- handle arguments of page/mainpage command ------------------- */
1599
1600<PageDocArg1>[^\n]*"\\ilinebr @ianchor"\{[^\‍]\n]*\}{B}{FILE} { // special case where the Markdown processor has rewritten
1601 // "@page label Title" as
1602 // "@page md_label Title\ilinebr @ianchor{Title} label"
1603 DString text = yytext;
1604 size_t start = text.find('{');
1605 size_t end = text.find('}',start+1);
1606 yyextra->current->name = text.mid(end+2);
1607 size_t istart = yyextra->current->name.find("\\ilinebr");
1608 if (istart != DString::npos)
1609 {
1610 DString rest = yyextra->current->name.mid(istart);
1611 unput_string(rest,rest.length());
1612 yyextra->current->name = yyextra->current->name.left(istart);
1613 }
1614 yyextra->current->args = text.mid(start+1,end-start-1);
1615 //printf("name='%s' title='%s'\n",qPrint(yyextra->current->name),qPrint(yyextra->current->args));
1616 BEGIN( PageDocArg2 );
1617 }
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:156
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
1618<PageDocArg1>{FILE} { // first argument; page name
1619 yyextra->current->name = stripQuotes(yytext);
1620 yyextra->current->args = "";
1621 BEGIN( PageDocArg2 );
1622 }
1623<PageDocArg1>{LC} { yyextra->lineNr++;
1624 addOutput(yyscanner,'\n');
1625 }
1626<PageDocArg1>{DOCNL} {
1627 warn(yyextra->fileName,yyextra->lineNr,
1628 "missing argument after \\page."
1629 );
1630 unput_string(yytext,yyleng);
1631 //if (*yytext=='\n') yyextra->lineNr++;
1632 //addOutput(yyscanner,'\n');
1633 BEGIN( Comment );
1634 }
1635<PageDocArg1>. { // ignore other stuff
1636 }
1637<PageDocArg2>{DOCNL} { // second argument; page title
1638 unput_string(yytext,yyleng);
1639 //if (*yytext=='\n') yyextra->lineNr++;
1640 //addOutput(yyscanner,'\n');
1641 addOutput(yyscanner," \\ifile \""+ yyextra->fileName);
1642 addOutput(yyscanner,"\" \\iline " + DString().setNum(yyextra->lineNr) + " \\ilinebr ");
1643 BEGIN( Comment );
1644 }
1645<PageDocArg2>{CMD}[<>] {
1646 // bug 748927
1647 DString tmp(yytext);
1648 tmp = substitute(substitute(tmp,"@<","&lt;"),"@>","&gt;");
1649 tmp = substitute(substitute(tmp,"\\<","&lt;"),"\\>","&gt;");
1650 yyextra->current->args += tmp;
1651 }
1652<PageDocArg2>. {
1653 yyextra->current->args += yytext;
1654 }
1655 /* --------- handle arguments of the param command ------------ */
1656<ParamArg1>{ID}/{B}*"," {
1657 addOutput(yyscanner,yytext);
1658 }
1659<ParamArg1>"," {
1660 addOutput(yyscanner," , ");
1661 }
1662<ParamArg1>{DOCNL} {
1663 if (*yytext=='\n') yyextra->lineNr++;
1664 addOutput(yyscanner," ");
1665 }
1666<ParamArg1>{ID} {
1667 addOutput(yyscanner,yytext);
1668 BEGIN( Comment );
1669 }
1670<ParamArg1>. {
1671 unput(yytext[0]);
1672 BEGIN( Comment );
1673 }
1674
1675 /* --------- handle arguments of the file/dir/example command ------------ */
1676
1677<FileDocArg1>{DOCNL} { // no file name specified
1678 unput_string(yytext,yyleng);
1679 //if (*yytext=='\n') yyextra->lineNr++;
1680 //addOutput(yyscanner,'\n');
1681 BEGIN( Comment );
1682 }
1683<FileDocArg1>{FILE} { // first argument; name
1684 yyextra->current->name = stripQuotes(yytext);
1685 BEGIN( Comment );
1686 }
1687<FileDocArg1>{LC} { yyextra->lineNr++;
1688 addOutput(yyscanner,'\n');
1689 }
1690<FileDocArg1>. { // ignore other stuff
1691 }
1692
1693 /* --------- handle arguments of the xrefitem command ------------ */
1694
1695<XRefItemParam1>{LABELID} { // first argument
1696 yyextra->newXRefItemKey=yytext;
1697 setOutput(yyscanner,OutputXRef);
1698 BEGIN(XRefItemParam2);
1699 }
1700<XRefItemParam1>{LC} { // line continuation
1701 yyextra->lineNr++;
1702 addOutput(yyscanner,'\n');
1703 }
1704<XRefItemParam1>{DOCNL} { // missing arguments
1705 warn(yyextra->fileName,yyextra->lineNr,
1706 "Missing first argument of \\xrefitem"
1707 );
1708 if (*yytext=='\n') yyextra->lineNr++;
1709 addOutput(yyscanner,'\n');
1710 yyextra->inContext = OutputDoc;
1711 BEGIN( Comment );
1712 }
1713<XRefItemParam1>. { // ignore other stuff
1714 }
1715
1716<XRefItemParam2>"\""[^\n\"]*"\"" { // second argument
1717 yyextra->xrefItemTitle = stripQuotes(yytext);
1718 BEGIN(XRefItemParam3);
1719 }
1720<XRefItemParam2>{LC} { // line continuation
1721 yyextra->lineNr++;
1722 addOutput(yyscanner,'\n');
1723 }
1724<XRefItemParam2>{DOCNL} { // missing argument
1725 warn(yyextra->fileName,yyextra->lineNr,
1726 "Missing second argument of \\xrefitem"
1727 );
1728 if (*yytext=='\n') yyextra->lineNr++;
1729 addOutput(yyscanner,'\n');
1730 yyextra->inContext = OutputDoc;
1731 BEGIN( Comment );
1732 }
1733<XRefItemParam2>. { // ignore other stuff
1734 }
1735
1736<XRefItemParam3>"\""[^\n\"]*"\"" { // third argument
1737 yyextra->xrefListTitle = stripQuotes(yytext);
1738 yyextra->xrefKind = XRef_Item;
1739 BEGIN( Comment );
1740 }
1741<XRefItemParam2,XRefItemParam3>{LC} { // line continuation
1742 yyextra->lineNr++;
1743 addOutput(yyscanner,'\n');
1744 }
1745<XRefItemParam3>{DOCNL} { // missing argument
1746 warn(yyextra->fileName,yyextra->lineNr,
1747 "Missing third argument of \\xrefitem"
1748 );
1749 if (*yytext=='\n') yyextra->lineNr++;
1750 addOutput(yyscanner,'\n');
1751 yyextra->inContext = OutputDoc;
1752 BEGIN( Comment );
1753 }
1754<XRefItemParam3>. { // ignore other stuff
1755 }
1756
1757
1758 /* ----- handle arguments of the relates(also)/memberof command ------- */
1759
1760<RelatesParam1>({ID}("::"|"."))*{ID} { // argument
1761 yyextra->current->relates = yytext;
1762 //if (yyextra->current->mGrpId!=DOX_NOGROUP)
1763 //{
1764 // memberGroupRelates = yytext;
1765 //}
1766 BEGIN( Comment );
1767 }
1768<RelatesParam1>{LC} { // line continuation
1769 yyextra->lineNr++;
1770 addOutput(yyscanner,'\n');
1771 }
1772<RelatesParam1>{DOCNL} { // missing argument
1773 warn(yyextra->fileName,yyextra->lineNr,
1774 "Missing argument of '\\{}' command",yyextra->currentCmd
1775 );
1776 unput_string(yytext,yyleng);
1777 //if (*yytext=='\n') yyextra->lineNr++;
1778 //addOutput(yyscanner,'\n');
1779 BEGIN( Comment );
1780 }
1781<RelatesParam1>. { // ignore other stuff
1782 }
1783
1784
1785 /* ----- handle arguments of the qualifier command ----- */
1786<Qualifier>{LABELID} { // unquoted version, simple label
1787 yyextra->current->qualifiers.emplace_back(yytext);
1788 BEGIN( Comment );
1789 }
1790<Qualifier>"\""[^\"]*"\"" { // quotes version, add without quotes
1791 std::string inp(yytext);
1792 yyextra->current->qualifiers.push_back(inp.substr(1,yyleng-2));
1793 BEGIN( Comment );
1794 }
1795<Qualifier>{DOCNL} { // missing argument
1796 warn(yyextra->fileName,yyextra->lineNr,
1797 "Missing argument of '\\{}' command",yyextra->currentCmd
1798 );
1799 unput_string(yytext,yyleng);
1800 BEGIN( Comment );
1801 }
1802<Qualifier>. {
1803 warn(yyextra->fileName,yyextra->lineNr,
1804 "Argument of '\\{}' command should be quoted",yyextra->currentCmd
1805 );
1806 unput_string(yytext,yyleng);
1807 BEGIN( Comment );
1808 }
1809 /* ----- handle arguments of the iline command ----- */
1810<ILine>{LINENR}/[\\@\n\.] |
1811<ILine>{LINENR}{B} {
1812 bool ok = false;
1813 int nr = DString(yytext).toInt(&ok);
1814 if (!ok)
1815 {
1816 warn(yyextra->fileName,yyextra->lineNr,"Invalid line number '{}' for iline command",yytext);
1817 }
1818 else
1819 {
1820 yyextra->lineNr = nr;
1821 }
1822 addOutput(yyscanner,yytext);
1823 if (YY_START == ILine)
1824 {
1825 BEGIN(Comment);
1826 }
1827 else
1828 {
1829 yyextra->sectionTitle+=yytext;
1830 BEGIN(SectionTitle);
1831 }
1832 }
1833<ILine,ILineSection>. {
1834 addOutput(yyscanner,yytext);
1835 if (YY_START == ILine)
1836 {
1837 BEGIN(Comment);
1838 }
1839 else
1840 {
1841 yyextra->sectionTitle+=yytext;
1842 BEGIN(SectionTitle);
1843 }
1844 }
1845
1846 /* ----- handle arguments of the iraise command ----- */
1847<IRaise>{B}*[0-9]+/[\\@\n\.] |
1848<IRaise>{B}*[0-9]+{B} {
1849 bool ok = false;
1850 int nr = DString(yytext).toInt(&ok);
1851 if (!ok)
1852 {
1853 warn(yyextra->fileName,yyextra->lineNr,"Invalid level '{}' for iraise command",yytext);
1854 }
1855 else
1856 {
1857 yyextra->raiseLevel = nr;
1858 }
1859 BEGIN(Comment);
1860 }
1861<IRaise>. {
1862 unput(yytext[0]);
1863 BEGIN(Comment);
1864 }
1865 /* ----- handle arguments of the iprefix command ----- */
1866
1867<IRaisePrefix>{B}*"\""({LABELID})?"\"" {
1868 DString text(yytext);
1869 yyextra->raisePrefix = text.stripWhiteSpace().mid(1,text.length()-2);
1870 addOutput(yyscanner,yytext);
1871 BEGIN(Comment);
1872 }
1873<IRaisePrefix>. {
1874 unput(yytext[0]);
1875 BEGIN(Comment);
1876 }
1877
1878
1879 /* ----- handle arguments of the ifile command ----- */
1880
1881<IFile,IFileSection>{FILE} {
1882 addOutput(yyscanner,yytext);
1883 DString text(yytext);
1884 if (yytext[0] == '\"') yyextra->fileName = text.mid(1,text.length()-2);
1885 else yyextra->fileName = yytext;
1886 if (YY_START == IFile)
1887 {
1888 BEGIN(Comment);
1889 }
1890 else
1891 {
1892 yyextra->sectionTitle+=yytext;
1893 BEGIN(SectionTitle);
1894 }
1895 }
1896
1897<LinkSection>[^\\@\n]* {
1898 yyextra->sectionTitle+=yytext;
1899 }
1900<LinkSection>{CMD}{CMD} {
1901 yyextra->sectionTitle+=yytext;
1902 }
1903<LinkSection>{DOCNL} {
1904 addOutput(yyscanner,yytext);
1905 if (*yytext == '\n') yyextra->lineNr++;
1906 yyextra->sectionTitle+=yytext;
1907 }
1908<LinkSection>{CMD}"endlink" {
1909 yyextra->sectionTitle+=yytext;
1910 BEGIN(SectionTitle);
1911 }
1912<LinkSection>. {
1913 yyextra->sectionTitle+=yytext;
1914 }
1915<LinkSection><<EOF>> {
1916 warn(yyextra->fileName,yyextra->lineNr,
1917 "reached end of comment while inside a '\\link' command, missing '\\endlink' command"
1918 );
1919 yyterminate();
1920 }
1921 /* ----- handle arguments of the relates(also)/addindex commands ----- */
1922
1923<LineParam>{CMD}{CMD} { // escaped command
1924 addOutput(yyscanner,yytext);
1925 }
1926<LineParam>{DOCNL} { // end of argument
1927 //if (*yytext=='\n') yyextra->lineNr++;
1928 //addOutput(yyscanner,'\n');
1929 unput_string(yytext,yyleng);
1930 BEGIN( Comment );
1931 }
1932<LineParam>{LC} { // line continuation
1933 yyextra->lineNr++;
1934 addOutput(yyscanner,'\n');
1935 }
1936<LineParam>({CMD}{CMD}){ID} { // escaped command
1937 addOutput(yyscanner,yytext);
1938 }
1939<LineParam>. { // ignore other stuff
1940 addOutput(yyscanner,*yytext);
1941 }
1942
1943 /* ----- handle arguments of the section/subsection/.. commands ------- */
1944
1945<SectionLabel>{LABELID} {
1946 yyextra->sectionLabel+=yytext;
1947 }
1948<SectionLabel>{CMD}"lineinfo"("{}")? {
1949 yyextra->sectionLabel += DString().setNum(yyextra->lineNr);
1950 }
1951<SectionLabel>{CMD}"fileinfo"("{"[^}]*"}")? {
1952 FileInfo fi(yyextra->fileName.str());
1953 bool hasOption = false;
1954 DString label;
1955 if (yytext[yyleng-1] == '}') // has parameters
1956 {
1957 StringVector optList;
1958 DString txt = yytext;
1959 DString optStr = txt.mid(10,yyleng-11).stripWhiteSpace();
1960 optList = split(optStr.str(),",");
1961 for (const auto &opt_ : optList)
1962 {
1963 DString optStripped = DString(opt_).stripWhiteSpace();
1964 std::string opt = optStripped.lower().str();
1965 DString result = fileInfoLookup(fi,opt);
1966 if (!result.empty())
1967 {
1968 if (hasOption) // oops: already found an option
1969 {
1970 warn(yyextra->fileName,yyextra->lineNr,"Multiple options specified with \\fileinfo, discarding '{}'", optStripped);
1971 }
1972 else
1973 {
1974 label = result;
1975 }
1976 hasOption = true;
1977 }
1978 else
1979 {
1980 warn(yyextra->fileName,yyextra->lineNr,"Unknown option specified with \\fileinfo: '{}'", optStripped);
1981 }
1982 }
1983 }
1984 if (!hasOption)
1985 {
1986 if (Config_getBool(FULL_PATH_NAMES))
1987 {
1988 label=stripFromPath(yyextra->fileName);
1989 }
1990 else
1991 {
1992 label=yyextra->fileName;
1993 }
1994 }
1995 escapeLabel(label);
1996 yyextra->sectionLabel+=label;
1997 }
DString lower() const
Definition dstring.h:331
#define Config_getBool(name)
Definition config.h:33
DString stripFromPath(const DString &path)
Definition util.cpp:251
1998<SectionLabel>{DOCNL} {
1999 yyextra->sectionTitle.clear();
2000 if (yyextra->sectionLabel.empty())
2001 { // missing argument
2002 warn(yyextra->fileName,yyextra->lineNr,
2003 "\\section command has no label"
2004 );
2005 }
2006 else
2007 {
2008 yyextra->sectionLabel=yyextra->raisePrefix+yyextra->sectionLabel;
2009 addOutput(yyscanner,yyextra->sectionLabel.data());
2010 addSection(yyscanner);
2011 }
2012 if (*yytext=='\n') yyextra->lineNr++;
2013 addOutput(yyscanner,'\n');
2014 BEGIN( Comment );
2015 }
2016<SectionLabel>. { // invalid character for section label
2017 if (yyextra->sectionLabel.empty())
2018 {
2019 warn(yyextra->fileName,yyextra->lineNr,
2020 "Invalid or missing section label"
2021 );
2022 BEGIN(Comment);
2023 }
2024 else
2025 {
2026 yyextra->sectionLabel=yyextra->raisePrefix+yyextra->sectionLabel;
2027 addOutput(yyscanner,yyextra->sectionLabel.data());
2028 yyextra->sectionTitle.clear();
2029 unput_string(yytext,yyleng);
2030 BEGIN(SectionTitle);
2031 }
2032 }
2033<SectionTitle>{STAopt}/"\n" { // end of section title
2034 addSection(yyscanner);
2035 addOutput(yyscanner,yytext);
2036 BEGIN( Comment );
2037 }
2038<SectionTitle>{STopt}"\\\\ilinebr" { // escaped end of section title
2039 yyextra->sectionTitle+=yytext;
2040 }
2041<SectionTitle>{STopt}/"\\ilinebr" { // end of section title
2042 addSection(yyscanner);
2043 addOutput(yyscanner,yytext);
2044 BEGIN( Comment );
2045 }
2046<SectionTitle>{B}*{CMD}"f$" {
2047 yyextra->formulaText="";
2048 yyextra->formulaPreText="$";
2049 yyextra->formulaPostText="";
2050 yyextra->formulaNewLines=0;
2051 BEGIN(ReadFormulaShortSection);
2052 }
2053<SectionTitle>{B}*{CMD}"f(" { // start of a inline formula
2054 yyextra->formulaText="";
2055 yyextra->formulaPreText="";
2056 yyextra->formulaPostText="";
2057 yyextra->formulaNewLines=0;
2058 BEGIN(ReadFormulaRoundSection);
2059 }
2060<SectionTitle>{B}*{CMD}"~"[a-z_A-Z-]* | // language switch command
2061<SectionTitle>{B}*{CMD}"f"[\‍[{] { // block formula
2062 setOutput(yyscanner,OutputDoc);
2063 addOutput(yyscanner," \\ilinebr ");
2064 addSection(yyscanner,false);
2065 warn(yyextra->fileName,yyextra->lineNr,
2066 "'\\{}' command is not allowed in section title, ending section title.",
2067 DString(yytext).stripWhiteSpace()
2068 );
2069 unput_string(yytext,yyleng);
2070 BEGIN(Comment);
2071 }
2072<SectionTitle>{LC} { // line continuation
2073 yyextra->lineNr++;
2074 addOutput(yyscanner,'\n');
2075 }
2076<SectionTitle>[^\n@\\‍]* { // any character without special meaning
2077 yyextra->sectionTitle+=yytext;
2078 addOutput(yyscanner,yytext);
2079 }
2080<SectionTitle>{B}*{CMD}{CMD} {
2081 yyextra->sectionTitle+=yytext;
2082 addOutput(yyscanner,yytext);
2083 }
2084<SectionTitle>{B}*{CMD}[a-z_A-Z]+"{"[^}]*"}"{B}* |
2085<SectionTitle>{B}*{CMD}[a-z_A-Z]+{B}* { // handling command in section title
2086 DString fullMatch = yytext;
2087 size_t idx = fullMatch.find('{');
2088 /* handle `f{` command as special case */
2089 if ((idx > 1) && (yytext[idx-1] == 'f') && (yytext[idx-2] == '\\' || yytext[idx-2] =='@')) REJECT;
2090 size_t idxEnd = fullMatch.find("}",idx+1);
2091 DString cmdName;
2092 StringVector optList;
2093 if (idx == DString::npos) // no options
2094 {
2095 cmdName = fullMatch.stripWhiteSpace().mid(1); // to remove {CMD}
2096 }
2097 else // options present
2098 {
2099 cmdName = fullMatch.left(idx).stripWhiteSpace().mid(1); // to remove {CMD}
2100 DString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace();
2101 optList = split(optStr.str(),",");
2102 }
2103 auto it = docCmdMap.find(cmdName.str());
2104 if (it!=docCmdMap.end()) // special action is required
2105 {
2106 switch (it->second.sectionHandling)
2107 {
2109 {
2110 int i=0;
2111 while (yytext[i]==' ' || yytext[i]=='\t') i++;
2112 yyextra->sectionTitle+=fullMatch.left(i);
2113 yyextra->sectionTitle+='@';
2114 yyextra->sectionTitle+=fullMatch.mid(i);
2115 addOutput(yyscanner,qPrint(fullMatch.left(i)));
2116 addOutput(yyscanner,'@');
2117 addOutput(yyscanner,qPrint(fullMatch.mid(i)));
2118 warn(yyextra->fileName,yyextra->lineNr,
2119 "'\\{}' command is not allowed in section title, escaping command.",cmdName
2120 );
2121 }
2122 break;
2124 {
2125 addSection(yyscanner,false);
2126 addOutput(yyscanner," \\ilinebr ");
2127 warn(yyextra->fileName,yyextra->lineNr,
2128 "'\\{}' command is not allowed in section title, ending section title.",cmdName
2129 );
2130 unput_string(yytext,yyleng);
2131 BEGIN(Comment);
2132 }
2133 break;
2135 {
2136 if (cmdName == "fileinfo")
2137 {
2138 int i=0;
2139 while (yytext[i]==' ' || yytext[i]=='\t') i++;
2140 yyextra->sectionTitle+=fullMatch.left(i);
2141 addOutput(yyscanner,fullMatch.left(i));
2142 handleFileInfoSection(yyscanner,cmdName,optList);
2143 if (idxEnd == DString::npos)
2144 {
2145 yyextra->sectionTitle+=fullMatch.mid(i+9);
2146 addOutput(yyscanner,fullMatch.mid(i+9));
2147 }
2148 else
2149 {
2150 yyextra->sectionTitle+=fullMatch.mid(idxEnd+1);
2151 addOutput(yyscanner,fullMatch.mid(idxEnd+1));
2152 }
2153 }
2154 else if (cmdName == "lineinfo")
2155 {
2156 int i=0;
2157 while (yytext[i]==' ' || yytext[i]=='\t') i++;
2158 yyextra->sectionTitle+=fullMatch.left(i);
2159 yyextra->sectionTitle+=DString().setNum(yyextra->lineNr);
2160 yyextra->sectionTitle+=' ';
2161 yyextra->sectionTitle+=fullMatch.mid(i+9);
2162 addOutput(yyscanner,fullMatch.left(i));
2163 addOutput(yyscanner,DString().setNum(yyextra->lineNr));
2164 addOutput(yyscanner,' ');
2165 addOutput(yyscanner,fullMatch.mid(i+9));
2166 }
2167 else if (cmdName == "raisewarning")
2168 {
2169 yyextra->raiseWarning = "";
2170 BEGIN(RaiseWarningSection);
2171 }
2172 else if (cmdName == "noop")
2173 {
2174 addSection(yyscanner,false);
2175 BEGIN(Noop);
2176 }
2177 else if (cmdName == "cite")
2178 {
2179 yyextra->sectionTitle+=yytext;
2180 addOutput(yyscanner,yytext);
2181 BEGIN(CiteLabelSection);
2182 }
2183 else if (cmdName == "iline")
2184 {
2185 yyextra->sectionTitle+=yytext;
2186 addOutput(yyscanner,yytext);
2187 BEGIN(ILineSection);
2188 }
2189 else if (cmdName == "ifile")
2190 {
2191 yyextra->sectionTitle+=yytext;
2192 addOutput(yyscanner,yytext);
2193 BEGIN(IFileSection);
2194 }
2195 else if ((cmdName == "anchor") || (cmdName == "ianchor"))
2196 {
2197 addOutput(yyscanner,"@"+cmdName);
2198 if (optList.empty())
2199 {
2200 yyextra -> anchorTitle = "";
2201 }
2202 else
2203 {
2204 addOutput(yyscanner,"{"+join(optList," ")+"}");
2205 yyextra -> anchorTitle = join(optList," ");
2206 }
2207 addOutput(yyscanner," ");
2208 BEGIN(AnchorLabelSection);
2209 }
2210 else if (cmdName == "link")
2211 {
2212 yyextra->sectionTitle+=yytext;
2213 BEGIN(LinkSection);
2214 }
2215 else
2216 {
2217 yyextra->sectionTitle+=yytext;
2218 warn(yyextra->fileName,yyextra->lineNr,
2219 "internal error '\\{}' command is to be replaced in section title.",cmdName
2220 );
2221 }
2222 }
2223 break;
2225 {
2226 yyextra->sectionTitle+=yytext;
2227 addOutput(yyscanner,yytext);
2228 }
2229 break;
2230 }
2231 }
2232 else
2233 {
2234 yyextra->sectionTitle+=yytext;
2235 addOutput(yyscanner,yytext);
2236 }
2237 }
DString & setNum(short n)
Definition dstring.h:541
const char * qPrint(const char *s)
Definition dstring.h:772
std::string join(const StringVector &sv, const std::string &delimiter)
create a string where the string in the vector are joined by the given delimiter
Definition stringutil.h:153
2238<SectionTitle>. { // anything else
2239 yyextra->sectionTitle+=yytext;
2240 addOutput(yyscanner,*yytext);
2241 }
2242
2243 /* ----- handle arguments of the subpage command ------- */
2244
2245<SubpageLabel>{FILE} { // first argument
2246 addOutput(yyscanner,yytext);
2247 // we add subpage labels as a kind of "inheritance" relation to prevent
2248 // needing to add another list to the Entry class.
2249 yyextra->current->extends.emplace_back(yytext,Protection::Public,Specifier::Normal);
2250 BEGIN(SubpageTitle);
2251 }
2252<SubpageLabel>{DOCNL} { // missing argument
2253 warn(yyextra->fileName,yyextra->lineNr,
2254 "\\subpage command has no label"
2255 );
2256 if (*yytext=='\n') yyextra->lineNr++;
2257 addOutput(yyscanner,'\n');
2258 BEGIN( Comment );
2259 }
2260<SubpageLabel>. {
2261 unput(yytext[0]);
2262 BEGIN( Comment );
2263 }
2264<SubpageTitle>{DOCNL} { // no title, end command
2265 addOutput(yyscanner,yytext);
2266 BEGIN( Comment );
2267 }
2268<SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command
2269 addOutput(yyscanner,yytext);
2270 BEGIN( Comment );
2271 }
2272<SubpageTitle>. { // no title, end of command
2273 unput(*yytext);
2274 BEGIN( Comment );
2275 }
2276
2277 /* ----- handle arguments of the anchor command ------- */
2278
2279<AnchorLabel,AnchorLabelSection>{LABELID} { // found argument
2280 DString lbl = yyextra->raisePrefix+yytext;
2281 addAnchor(yyscanner,lbl, yyextra->anchorTitle);
2282 addOutput(yyscanner,lbl.data());
2283 if (YY_START == AnchorLabel)
2284 {
2285 BEGIN(Comment);
2286 }
2287 else
2288 {
2289 BEGIN(SectionTitle);
2290 }
2291 }
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:162
2292<AnchorLabel,AnchorLabelSection>{DOCNL} { // missing argument
2293 warn(yyextra->fileName,yyextra->lineNr,
2294 "\\anchor command has no label"
2295 );
2296 if (*yytext=='\n') yyextra->lineNr++;
2297 addOutput(yyscanner,'\n');
2298 if (YY_START == AnchorLabel)
2299 {
2300 BEGIN(Comment);
2301 }
2302 else
2303 {
2304 BEGIN(SectionTitle);
2305 }
2306 }
2307<AnchorLabel,AnchorLabelSection>. { // invalid character for anchor label
2308 warn(yyextra->fileName,yyextra->lineNr,
2309 "Invalid or missing anchor label"
2310 );
2311 addOutput(yyscanner,yytext);
2312 if (YY_START == AnchorLabel)
2313 {
2314 BEGIN(Comment);
2315 }
2316 else
2317 {
2318 BEGIN(SectionTitle);
2319 }
2320 }
2321
2322 /* ----- handle arguments of the anchor command ------- */
2323
2324<RequirementLabel>{REQID} { // found argument
2325 yyextra->current->name = yytext;
2326 yyextra->current->type.clear();
2327 BEGIN( RequirementTitle );
2328 }
2329<SatisfiesLabel>{REQID} { // found argument
2330 yyextra->reqId = yytext;
2331 yyextra->reqTitle.clear();
2332 BEGIN( SatisfiesTitle );
2333 }
2334<VerifiesLabel>{REQID} { // found argument
2335 yyextra->reqId = yytext;
2336 yyextra->reqTitle.clear();
2337 BEGIN( VerifiesTitle );
2338 }
2339<RequirementLabel,SatisfiesLabel,VerifiesLabel>"\\"{B}*"\n" { // line continuation
2340 yyextra->lineNr++;
2341 addOutput(yyscanner,'\n');
2342 }
2343<RequirementLabel,SatisfiesLabel,VerifiesLabel>{DOCNL} { // missing argument
2344 warn(yyextra->fileName,yyextra->lineNr,
2345 "missing requirement ID after \\requirement command"
2346 );
2347 unput_string(yytext,yyleng);
2348 BEGIN( Comment );
2349 }
2350<RequirementLabel,SatisfiesLabel,VerifiesLabel>. { // invalid character for requirement label
2351 }
2352
2353<RequirementTitle,SatisfiesTitle,VerifiesTitle>"\\"{B}*"\n" { // line continuation
2354 yyextra->lineNr++;
2355 addOutput(yyscanner,'\n');
2356 }
2357<RequirementTitle>[^\n\\‍]+ { // title (stored in type)
2358 yyextra->current->type += yytext;
2359 }
2360<SatisfiesTitle,VerifiesTitle>[^\n\\@]+ { // title (stored in type)
2361 yyextra->reqTitle += yytext;
2362 }
2363<RequirementTitle>({CMD}("verifies"|"satisfies"|"requirement"){B}+)|{DOCNL}+ {
2364 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
2365 unput_string(yytext,yyleng);
2366 addRequirementId(yyscanner);
2367 BEGIN( Comment );
2368 }
2369<SatisfiesTitle>({CMD}("verifies"|"satisfies"|"requirement"){B}+)|{DOCNL}+ {
2370 yyextra->reqTitle = yyextra->reqTitle.stripWhiteSpace();
2371 unput_string(yytext,yyleng);
2372 if (yyextra->current->section.isRequirementDoc())
2373 {
2374 warn(yyextra->fileName,yyextra->lineNr,
2375 "@satisfies command is not allowed in documentation of a requirement. Put in at the place where the requirement is implemented."
2376 );
2377 }
2378 else
2379 {
2380 yyextra->current->rqli.emplace_back(RequirementRefType::Satisfies,
2381 yyextra->reqId,
2382 yyextra->reqTitle,
2383 yyextra->fileName,
2384 yyextra->lineNr);
2385 }
2386 BEGIN( Comment );
2387 }
2388<VerifiesTitle>({CMD}("verifies"|"satisfies"|"requirement"){B}+)|{DOCNL}+ {
2389 yyextra->reqTitle = yyextra->reqTitle.stripWhiteSpace();
2390 unput_string(yytext,yyleng);
2391 if (yyextra->current->section.isRequirementDoc())
2392 {
2393 warn(yyextra->fileName,yyextra->lineNr,
2394 "@verifies command is not allowed in documentation of a requirement. Put in at the place where the requirement is tested."
2395 );
2396 }
2397 else
2398 {
2399 yyextra->current->rqli.emplace_back(RequirementRefType::Verifies,
2400 yyextra->reqId,
2401 yyextra->reqTitle,
2402 yyextra->fileName,
2403 yyextra->lineNr);
2404 }
2405 BEGIN( Comment );
2406 }
2407<RequirementTitle>. { // title (stored in type)
2408 yyextra->current->type += yytext;
2409 }
2410<SatisfiesTitle,VerifiesTitle>. { // title (stored in reqTitle)
2411 yyextra->reqTitle += yytext;
2412 }
2413
2414
2415 /* ----- handle arguments of the preformatted block commands ------- */
2416
2417<FormatBlock>{CMD}("endverbatim"|"endiverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endicode"|"endmsc"|"endmermaid")/{NW} { // possible ends
2418 addOutput(yyscanner,yytext);
2419 if (&yytext[4]==yyextra->blockName) // found end of the block
2420 {
2421 BEGIN(Comment);
2422 }
2423 }
2424<FormatBlock>{CMD}"enduml" {
2425 addOutput(yyscanner,yytext);
2426 if (yyextra->blockName=="startuml") // found end of the block
2427 {
2428 BEGIN(Comment);
2429 }
2430 }
2431<FormatBlock>[^ \@\*\/\\\n]* { // some word
2432 addOutput(yyscanner,yytext);
2433 }
2434<FormatBlock>{DOCNL} { // new line
2435 if (*yytext=='\n') yyextra->lineNr++;
2436 addOutput(yyscanner,'\n');
2437 }
2438<FormatBlock>{CCS} { // start of a C-comment
2439 if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" ||
2440 yyextra->blockName=="icode" || yyextra->blockName=="iverbatim"||
2441 yyextra->blockName=="iliteral"
2442 )
2443 ) yyextra->commentCount++;
2444 addOutput(yyscanner,yytext);
2445 }
2446<FormatBlock>{CCE} { // end of a C-comment
2447 addOutput(yyscanner,yytext);
2448 if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim" ||
2449 yyextra->blockName=="icode" || yyextra->blockName=="iverbatim"||
2450 yyextra->blockName=="iliteral"
2451 )
2452 )
2453 {
2454 yyextra->commentCount--;
2455 if (yyextra->commentCount<0)
2456 {
2457 DString endTag = "end"+yyextra->blockName;
2458 if (yyextra->blockName=="startuml") endTag="enduml";
2459 warn(yyextra->fileName,yyextra->lineNr,
2460 "found */ without matching /* while inside a \\{} block! Perhaps a missing \\{}?",
2461 yyextra->blockName,endTag);
2462 }
2463 }
2464 }
2465<FormatBlock>. {
2466 addOutput(yyscanner,*yytext);
2467 }
2468<FormatBlock><<EOF>> {
2469 DString endTag = "end"+yyextra->blockName;
2470 if (yyextra->blockName=="startuml") endTag="enduml";
2471 warn(yyextra->fileName,yyextra->lineNr,
2472 "reached end of comment while inside a \\{} block; check for missing \\{} tag!",
2473 yyextra->blockName,endTag
2474 );
2475 yyterminate();
2476 }
2477
2478 /* ----- handle arguments of if/ifnot commands ------- */
2479
2480<GuardParam>{B}*"(" {
2481 yyextra->guardExpr=yytext;
2482 yyextra->roundCount=1;
2483 BEGIN(GuardExpr);
2484 }
2485<GuardExpr>[^()]* {
2486 yyextra->guardExpr+=yytext;
2487 lineCount(yyscanner);
2488 }
2489<GuardExpr>"(" {
2490 yyextra->guardExpr+=yytext;
2491 yyextra->roundCount++;
2492 }
2493<GuardExpr>")" {
2494 yyextra->guardExpr+=yytext;
2495 yyextra->roundCount--;
2496 if (yyextra->roundCount==0)
2497 {
2498 handleGuard(yyscanner,yyextra->guardExpr);
2499 }
2500 }
2501<GuardExpr>\n {
2502 warn(yyextra->fileName,yyextra->lineNr,
2503 "invalid expression '{}' for yyextra->guards",yyextra->guardExpr);
2504 unput(*yytext);
2505 BEGIN(GuardParam);
2506 }
2507<GuardParam>{B}*{CMD}doxyconfig{B}+{DOXYCFG} {
2508 handleGuard(yyscanner,yytext);
2509 }
2510<GuardParam>{B}*[a-z_A-Z0-9.\-]+({B}*{CMD}doxyconfig{B}+{DOXYCFG})? { // parameter of if/ifnot yyextra->guards
2511 handleGuard(yyscanner,yytext);
2512 }
2513<GuardParam>{DOCNL} { // end of argument
2514 //next line is commented out due to bug620924
2515 //addOutput(yyscanner,'\n');
2516 addIlineBreak(yyscanner,yyextra->lineNr);
2517 unput_string(yytext,yyleng);
2518 handleGuard(yyscanner,DString());
2519 }
2520<GuardParam>{LC} { // line continuation
2521 yyextra->lineNr++;
2522 addOutput(yyscanner,'\n');
2523 }
2524<GuardParam>. { // empty condition
2525 unput(*yytext);
2526 handleGuard(yyscanner,DString());
2527 }
2528<GuardParamEnd>{B}*{DOCNL} {
2529 lineCount(yyscanner);
2530 yyextra->spaceBeforeIf.clear();
2531 addIlineBreak(yyscanner,yyextra->lineNr);
2532 BEGIN(Comment);
2533 }
2534<GuardParamEnd>{B}* {
2535 if (!yyextra->spaceBeforeIf.empty()) // needed for 665313 in combination with bug620924
2536 {
2537 addOutput(yyscanner,yyextra->spaceBeforeIf);
2538 }
2539 yyextra->spaceBeforeIf.clear();
2540 addIlineBreak(yyscanner,yyextra->lineNr);
2541 BEGIN(Comment);
2542 }
2543<GuardParamEnd>. {
2544 unput(*yytext);
2545 addIlineBreak(yyscanner,yyextra->lineNr);
2546 BEGIN(Comment);
2547 }
2548
2549 /* ----- handle skipping of conditional sections ------- */
2550
2551<SkipGuardedSection>{CMD}"ifnot"/{NW} {
2552 yyextra->guardType = Guard_IfNot;
2553 yyextra->guards->emplace(false);
2554 BEGIN( GuardParam );
2555 }
2556<SkipGuardedSection>{CMD}"if"/{NW} {
2557 yyextra->guardType = Guard_If;
2558 yyextra->guards->emplace(false);
2559 BEGIN( GuardParam );
2560 }
2561<SkipGuardedSection>{CMD}"endif"/{NW} {
2562 if (yyextra->guards->empty())
2563 {
2564 warn(yyextra->fileName,yyextra->lineNr,
2565 "found \\endif without matching start command");
2566 BEGIN( Comment );
2567 }
2568 else
2569 {
2570 yyextra->guards->pop();
2571 if (yyextra->guards->empty())
2572 {
2573 BEGIN( GuardParamEnd );
2574 }
2575 else
2576 {
2577 if (yyextra->guards->top().isEnabled())
2578 {
2579 BEGIN( GuardParamEnd );
2580 }
2581 else
2582 {
2583 BEGIN( SkipGuardedSection );
2584 }
2585 }
2586 }
2587 }
2588<SkipGuardedSection>{CMD}"else"/{NW} {
2589 if (yyextra->guards->empty())
2590 {
2591 warn(yyextra->fileName,yyextra->lineNr,
2592 "found \\else without matching start command");
2593 }
2594 else if (yyextra->guards->top().hasElse())
2595 {
2596 warn(yyextra->fileName,yyextra->lineNr,
2597 "found multiple \\else commands in same \\if construct");
2598 yyextra->guards->top().setEnabled(false);
2599 BEGIN( SkipGuardedSection );
2600 }
2601 else if (!yyextra->guards->top().parentVisible())
2602 {
2603 yyextra->guards->top().setEnabled(false);
2604 BEGIN( SkipGuardedSection );
2605 }
2606 else
2607 {
2608 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2609 yyextra->guards->top().setElse();
2610 if (!yyextra->guards->top().parentVisible())
2611 {
2612 yyextra->guards->top().setEnabled(false);
2613 BEGIN( SkipGuardedSection );
2614 }
2615 else if (yyextra->guards->top().isEnabledFound())
2616 {
2617 yyextra->guards->top().setEnabled(false);
2618 BEGIN( SkipGuardedSection );
2619 }
2620 else
2621 {
2622 yyextra->guards->top().setEnabled(true);
2623 BEGIN( GuardParamEnd );
2624 }
2625 }
2626 }
2627<SkipGuardedSection>{CMD}"elseif"/{NW} {
2628 if (yyextra->guards->empty())
2629 {
2630 warn(yyextra->fileName,yyextra->lineNr,
2631 "found \\elseif without matching start command");
2632 }
2633 else if (yyextra->guards->top().hasElse())
2634 {
2635 warn(yyextra->fileName,yyextra->lineNr,
2636 "found \\elseif command after \\else command was given in \\if construct");
2637 yyextra->guardType = Guard_ElseIf;
2638 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2639 yyextra->guards->top().setEnabled(false);
2640 BEGIN( GuardParam );
2641 }
2642 else
2643 {
2644 yyextra->guardType = Guard_ElseIf;
2645 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2646 yyextra->guards->top().setEnabled(false);
2647 BEGIN( GuardParam );
2648 }
2649 }
2650<SkipGuardedSection>{DOCNL} { // skip line
2651 if (*yytext=='\n') yyextra->lineNr++;
2652 //addOutput(yyscanner,'\n');
2653 }
2654<SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters
2655 }
2656<SkipGuardedSection>{CMD}{CMD} |
2657<SkipGuardedSection>. { // any other character
2658 }
2659
2660
2661 /* ----- handle skipping of internal section ------- */
2662
2663<SkipInternal>{DOCNL} { // skip line
2664 if (*yytext=='\n') yyextra->lineNr++;
2665 addOutput(yyscanner,'\n');
2666 }
2667<SkipInternal>{CMD}"if"/[ \t] {
2668 yyextra->condCount++;
2669 }
2670<SkipInternal>{CMD}"ifnot"/[ \t] {
2671 yyextra->condCount++;
2672 }
2673<SkipInternal>{CMD}/"endif" {
2674 yyextra->condCount--;
2675 if (yyextra->condCount<0) // handle conditional section around of \internal, see bug607743
2676 {
2677 unput('\\');
2678 BEGIN(Comment);
2679 }
2680 }
2681<SkipInternal>{CMD}/"section"[ \t] {
2682 if (yyextra->sectionLevel>0)
2683 {
2684 unput('\\');
2685 BEGIN(Comment);
2686 }
2687 }
2688<SkipInternal>{CMD}/"subsection"[ \t] {
2689 if (yyextra->sectionLevel>1)
2690 {
2691 unput('\\');
2692 BEGIN(Comment);
2693 }
2694 }
2695<SkipInternal>{CMD}/"subsubsection"[ \t] {
2696 if (yyextra->sectionLevel>2)
2697 {
2698 unput('\\');
2699 BEGIN(Comment);
2700 }
2701 }
2702<SkipInternal>{CMD}/"paragraph"[ \t] {
2703 if (yyextra->sectionLevel>3)
2704 {
2705 unput('\\');
2706 BEGIN(Comment);
2707 }
2708 }
2709<SkipInternal>{CMD}/"subparagraph"[ \t] {
2710 if (yyextra->sectionLevel>4)
2711 {
2712 unput('\\');
2713 BEGIN(Comment);
2714 }
2715 }
2716<SkipInternal>{CMD}/"subsubparagraph"[ \t] {
2717 if (yyextra->sectionLevel>5)
2718 {
2719 unput('\\');
2720 BEGIN(Comment);
2721 }
2722 }
2723<SkipInternal>{CMD}"endinternal"[ \t]* {
2724 BEGIN(Comment);
2725 }
2726<SkipInternal>[^ \\@\n]+ { // skip non-special characters
2727 }
2728<SkipInternal>. { // any other character
2729 }
2730
2731
2732 /* ----- handle argument of name command ------- */
2733
2734<NameParam>{DOCNL} { // end of argument
2735 //if (*yytext=='\n') yyextra->lineNr++;
2736 //addOutput(yyscanner,'\n');
2737 unput_string(yytext,yyleng);
2738 BEGIN( Comment );
2739 }
2740<NameParam>{LC} { // line continuation
2741 yyextra->lineNr++;
2742 addOutput(yyscanner,'\n');
2743 yyextra->docGroup.appendHeader(' ');
2744 }
2745<NameParam>. { // ignore other stuff
2746 yyextra->docGroup.appendHeader(*yytext);
2747 yyextra->current->name+=*yytext;
2748 }
2749
2750 /* ----- handle argument of noop command ------- */
2751<Noop>{DOCNL} { // end of argument
2752 if (*yytext=='\n')
2753 {
2754 yyextra->lineNr++;
2755 addOutput(yyscanner,'\n');
2756 }
2757 BEGIN( Comment );
2758 }
2759<Noop>. { // ignore other stuff
2760 }
2761 /* ----- handle argument of raisewarning command ------- */
2762<RaiseWarning,RaiseWarningSection>{DOCNL} { // end of argument
2763 warn_doc_error(yyextra->fileName,yyextra->lineNr,
2764 "{}",yyextra->raiseWarning);
2765 yyextra->raiseWarning = "";
2766 if (*yytext=='\n') yyextra->lineNr++;
2767 addOutput(yyscanner,'\n');
2768 if (YY_START == RaiseWarning)
2769 {
2770 BEGIN(Comment);
2771 }
2772 else
2773 {
2774 yyextra->sectionTitle+=yytext;
2775 BEGIN(SectionTitle);
2776 }
2777 }
#define warn_doc_error(file, line, fmt,...)
Definition message.h:112
2778<RaiseWarning,RaiseWarningSection>. { // ignore other stuff
2779 yyextra->raiseWarning += yytext;
2780 }
2781 /* ----- handle argument of ingroup command ------- */
2782
2783<InGroupParam>{LABELID} { // group id
2784 yyextra->current->groups.emplace_back(
2786 );
2787 yyextra->inGroupParamFound=true;
2788 }
@ GROUPING_INGROUP
membership in group was defined by @ingroup
Definition types.h:236
2789<InGroupParam>{DOCNL} { // missing argument
2790 if (!yyextra->inGroupParamFound)
2791 {
2792 warn(yyextra->fileName,yyextra->lineNr,
2793 "Missing group name for \\ingroup command"
2794 );
2795 }
2796 //if (*yytext=='\n') yyextra->lineNr++;
2797 //addOutput(yyscanner,'\n');
2798 unput_string(yytext,yyleng);
2799 BEGIN( Comment );
2800 }
2801<InGroupParam>{LC} { // line continuation
2802 yyextra->lineNr++;
2803 addOutput(yyscanner,'\n');
2804 }
2805<InGroupParam>. { // ignore other stuff
2806 addOutput(yyscanner,*yytext);
2807 }
2808
2809 /* ----- handle argument of fn command ------- */
2810
2811<FnParam>{DOCNL} { // end of argument
2812 if (yyextra->braceCount==0)
2813 {
2814 if (yyextra->functionProto.stripWhiteSpace().empty())
2815 {
2816 warn(yyextra->fileName,yyextra->lineNr,
2817 "missing argument after '\\{}'.",yyextra->currentCmd
2818 );
2819 }
2820 else
2821 {
2822 makeStructuralIndicator(yyscanner,yyextra->currentMakeEntryType);
2823 yyextra->langParser->parsePrototype(yyextra->functionProto);
2824 }
2825 unput_string(yytext,yyleng);
2826 BEGIN( Comment );
2827 }
2828 }
2829<FnParam>{LC} { // line continuation
2830 yyextra->lineNr++;
2831 yyextra->functionProto+=' ';
2832 }
2833<FnParam>[^@\\\n()]+ { // non-special characters
2834 yyextra->functionProto+=yytext;
2835 }
2836<FnParam>"(" {
2837 yyextra->functionProto+=yytext;
2838 yyextra->braceCount++;
2839 }
2840<FnParam>")" {
2841 yyextra->functionProto+=yytext;
2842 yyextra->braceCount--;
2843 }
2844<FnParam>. { // add other stuff
2845 yyextra->functionProto+=*yytext;
2846 }
2847
2848
2849 /* ----- handle argument of overload command ------- */
2850
2851
2852<OverloadParam>{DOCNL} { // end of argument
2853 if (*yytext=='\n') yyextra->lineNr++;
2854 if (yyextra->functionProto.stripWhiteSpace().empty())
2855 { // plain overload command
2857 addOutput(yyscanner,'\n');
2858 }
2859 else // overload declaration
2860 {
2861 makeStructuralIndicator(yyscanner,EntryType::makeOverloadDoc);
2862 yyextra->langParser->parsePrototype(yyextra->functionProto);
2863 }
2864 BEGIN( Comment );
2865 }
virtual DString trOverloadText()=0
Translator * theTranslator
Definition language.cpp:71
2866<OverloadParam>{LC} { // line continuation
2867 yyextra->lineNr++;
2868 yyextra->functionProto+=' ';
2869 }
2870<OverloadParam>. { // add other stuff
2871 yyextra->functionProto+=*yytext;
2872 }
2873
2874 /* ----- handle argument of inherit command ------- */
2875
2876<InheritParam>({ID}("::"|"."))*{ID} { // found argument
2877 yyextra->current->extends.emplace_back(
2878 removeRedundantWhiteSpace(yytext),Protection::Public,Specifier::Normal
2879 );
2880 BEGIN( Comment );
2881 }
2882<InheritParam>{DOCNL} { // missing argument
2883 warn(yyextra->fileName,yyextra->lineNr,
2884 "\\inherit command has no argument"
2885 );
2886 if (*yytext=='\n') yyextra->lineNr++;
2887 addOutput(yyscanner,'\n');
2888 BEGIN( Comment );
2889 }
2890<InheritParam>. { // invalid character for anchor label
2891 warn(yyextra->fileName,yyextra->lineNr,
2892 "Invalid or missing name for \\inherit command"
2893 );
2894 BEGIN(Comment);
2895 }
2896
2897 /* ----- handle argument of extends and implements commands ------- */
2898
2899<ExtendsParam>({ID}("::"|"."))*{ID} { // found argument
2900 yyextra->current->extends.emplace_back(
2901 removeRedundantWhiteSpace(yytext),Protection::Public,Specifier::Normal
2902 );
2903 BEGIN( Comment );
2904 }
2905<ExtendsParam>{DOCNL} { // missing argument
2906 warn(yyextra->fileName,yyextra->lineNr,
2907 "'\\{}' command has no argument",yyextra->currentCmd
2908 );
2909 //if (*yytext=='\n') yyextra->lineNr++;
2910 //addOutput(yyscanner,'\n');
2911 unput_string(yytext,yyleng);
2912 BEGIN( Comment );
2913 }
2914<ExtendsParam>. { // ignore other stuff
2915 }
2916
2917 /* ----- handle language specific sections ------- */
2918
2919<SkipLang>{CMD}"~"[a-zA-Z-]* { /* language switch */
2920 DString langId(&yytext[2]);
2921 if (!langId.empty() && !Config_isAvailableEnum(OUTPUT_LANGUAGE,langId))
2922 {
2923 warn(yyextra->fileName,yyextra->lineNr,
2924 "non supported language '{}' specified in '{}'",langId,DString(yytext).stripWhiteSpace());
2925 }
2926 else if (langId.empty() ||
2927 dstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE),langId)==0)
2928 { // enable language specific section
2929 BEGIN(Comment);
2930 }
2931 }
2932<SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */
2933 }
2934<SkipLang>{DOCNL} { /* new line in verbatim block */
2935 if (*yytext=='\n') yyextra->lineNr++;
2936 }
2937<SkipLang>. { /* any other character */
2938 }
2939
2940 /* ----- handle arguments of the cite command ------- */
2941
2942<CiteLabel,CiteLabelSection>{CITEID} { // found argument
2943 addCite(yyscanner);
2944 addOutput(yyscanner,yytext);
2945 if (YY_START == CiteLabel)
2946 {
2947 BEGIN(Comment);
2948 }
2949 else
2950 {
2951 yyextra->sectionTitle+=yytext;
2952 BEGIN(SectionTitle);
2953 }
2954 }
2955<CiteLabel,CiteLabelSection>{DOCNL} { // missing argument
2956 warn(yyextra->fileName,yyextra->lineNr,
2957 "\\cite command has no label"
2958 );
2959 //if (*yytext=='\n') yyextra->lineNr++;
2960 //addOutput(yyscanner,'\n');
2961 if (YY_START == CiteLabel)
2962 {
2963 unput_string(yytext,yyleng);
2964 BEGIN(Comment);
2965 }
2966 else
2967 {
2968 yyextra->sectionTitle+=yytext;
2969 unput_string(yytext,yyleng);
2970 BEGIN(SectionTitle);
2971 }
2972 }
2973<CiteLabel,CiteLabelSection>. { // invalid character for cite label
2974 warn(yyextra->fileName,yyextra->lineNr,
2975 "Invalid or missing cite label"
2976 );
2977 if (YY_START == CiteLabel)
2978 {
2979 BEGIN(Comment);
2980 }
2981 else
2982 {
2983 yyextra->sectionTitle+=yytext;
2984 BEGIN(SectionTitle);
2985 }
2986 }
2987
2988 /* ----- handle argument of the copydoc command ------- */
2989
2990<CopyDoc><<EOF>> {
2991 setOutput(yyscanner,OutputDoc);
2992 addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails ");
2993 addOutput(yyscanner,yyextra->copyDocArg);
2994 addOutput(yyscanner,"\n");
2995 BEGIN(Comment);
2996 }
2997<CopyDoc>"<"[/]?{TABLEDEL}">" {
2998 if (yyextra->braceCount==0)
2999 {
3000 setOutput(yyscanner,OutputDoc);
3001 addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails ");
3002 addOutput(yyscanner,yyextra->copyDocArg);
3003 addOutput(yyscanner,yytext);
3004 BEGIN(Comment);
3005 }
3006 }
3007<CopyDoc>{DOCNL} {
3008 if (*yytext=='\n') yyextra->lineNr++;
3009 if (yyextra->braceCount==0)
3010 {
3011 setOutput(yyscanner,OutputDoc);
3012 addOutput(yyscanner," \\ilinebr\\ilinebr\\copydetails ");
3013 addOutput(yyscanner,yyextra->copyDocArg);
3014 addOutput(yyscanner,"\n");
3015 BEGIN(Comment);
3016 }
3017 }
3018<CopyDoc>{LC} { // line continuation
3019 yyextra->lineNr++;
3020 }
3021<CopyDoc>[^@\\\n()<]+ { // non-special characters
3022 yyextra->copyDocArg+=yytext;
3023 addOutput(yyscanner,yytext);
3024 }
3025<CopyDoc>"(" {
3026 yyextra->copyDocArg+=yytext;
3027 addOutput(yyscanner,yytext);
3028 yyextra->braceCount++;
3029 }
3030<CopyDoc>")" {
3031 yyextra->copyDocArg+=yytext;
3032 addOutput(yyscanner,yytext);
3033 yyextra->braceCount--;
3034 }
3035<CopyDoc>. {
3036 yyextra->copyDocArg+=yytext;
3037 addOutput(yyscanner,yytext);
3038 }
3039
3040 /*
3041<*>. { fprintf(stderr,"Lex scanner %s %sdefault rule for state %s: #%s#\n", __FILE__,!yyextra->fileName.empty() ? ("(" + yyextra->fileName +") ").data(): "",stateToString(YY_START),yytext);}
3042<*>\n { fprintf(stderr,"Lex scanner %s %sdefault rule newline for state %s.\n", __FILE__, !yyextra->fileName.empty() ? ("(" + yyextra->fileName +") ").data(): "",stateToString(YY_START));}
3043 */
3044
3045%%
3046
3047//----------------------------------------------------------------------------
3048
3049static bool handleBrief(yyscan_t yyscanner,const DString &, const StringVector &)
3050{
3051 //printf("handleBrief\n");
3052 setOutput(yyscanner,OutputBrief);
3053 return false;
3054}
3055
3056static bool handleFn(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3057{
3058 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3059 yyextra->braceCount=0;
3060 yyextra->functionProto.clear();
3061 yyextra->currentCmd = cmd;
3062 yyextra->currentMakeEntryType = EntryType::makeMemberDoc;
3063 BEGIN( FnParam );
3064 return checkStructuralIndicator(yyscanner);
3065}
3066
3067static bool handleDef(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3068{
3069 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3070 yyextra->functionProto.clear();
3071 yyextra->braceCount=0;
3072 yyextra->currentCmd = cmd;
3073 yyextra->currentMakeEntryType = EntryType::makeDefineDoc;
3074 BEGIN( FnParam );
3075 return checkStructuralIndicator(yyscanner);
3076}
3077
3078static bool handleOverload(yyscan_t yyscanner,const DString &, const StringVector &)
3079{
3080 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3081 yyextra->functionProto.clear();
3082 BEGIN(OverloadParam);
3083 return false;
3084}
3085
3086static bool handleEnum(yyscan_t yyscanner,const DString &, const StringVector &)
3087{
3088 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3089 yyextra->currentMakeEntryType = EntryType::makeEnumDoc;
3090 BEGIN( EnumDocArg1 );
3091 return checkStructuralIndicator(yyscanner);
3092}
3093
3094static bool handleDefGroup(yyscan_t yyscanner,const DString &, const StringVector &)
3095{
3096 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3097 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeGroupDoc);
3098 yyextra->current->groupDocType = Entry::GROUPDOC_NORMAL;
3099 BEGIN( GroupDocArg1 );
3100 return stop;
3101}
3102
3103static bool handleAddToGroup(yyscan_t yyscanner,const DString &, const StringVector &)
3104{
3105 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3106 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeGroupDoc);
3107 yyextra->current->groupDocType = Entry::GROUPDOC_ADD;
3108 BEGIN( GroupDocArg1 );
3109 return stop;
3110}
3111
3112static bool handleWeakGroup(yyscan_t yyscanner,const DString &, const StringVector &)
3113{
3114 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3115 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeGroupDoc);
3116 yyextra->current->groupDocType = Entry::GROUPDOC_WEAK;
3117 BEGIN( GroupDocArg1 );
3118 return stop;
3119}
3120
3121static bool handleNamespace(yyscan_t yyscanner,const DString &, const StringVector &)
3122{
3123 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3124 yyextra->currentMakeEntryType = EntryType::makeNamespaceDoc;
3125 BEGIN( NameSpaceDocArg1 );
3126 return checkStructuralIndicator(yyscanner);
3127}
3128
3129static bool handlePackage(yyscan_t yyscanner,const DString &, const StringVector &)
3130{
3131 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3132 bool stop=makeStructuralIndicator(yyscanner,EntryType::makePackageDoc);
3133 BEGIN( PackageDocArg1 );
3134 return stop;
3135}
3136
3137static bool handleClass(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3138{
3139 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3140 yyextra->currentCmd = cmd;
3141 yyextra->currentMakeEntryType = EntryType::makeClassDoc;
3142 BEGIN( ClassDocArg1 );
3143 return checkStructuralIndicator(yyscanner);
3144}
3145
3146static bool handleConcept(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3147{
3148 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3149 yyextra->currentCmd = cmd;
3150 yyextra->currentMakeEntryType = EntryType::makeConceptDoc;
3151 BEGIN( ConceptDocArg1 );
3152 return checkStructuralIndicator(yyscanner);
3153}
3154
3155static bool handleModule(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3156{
3157 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3158 yyextra->currentCmd = cmd;
3159 yyextra->currentMakeEntryType = EntryType::makeModuleDoc;
3160 BEGIN( ModuleDocArg1 );
3161 return checkStructuralIndicator(yyscanner);
3162}
3163
3164static bool handleHeaderFile(yyscan_t yyscanner,const DString &, const StringVector &)
3165{
3166 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3167 BEGIN( ClassDocArg2 );
3168 return false;
3169}
3170
3171static bool handleProtocol(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3172{ // Obj-C protocol
3173 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3174 yyextra->currentCmd = cmd;
3175 yyextra->currentMakeEntryType = EntryType::makeProtocolDoc;
3176 BEGIN( ClassDocArg1 );
3177 return checkStructuralIndicator(yyscanner);
3178}
3179
3180static bool handleCategory(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3181{ // Obj-C category
3182 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3183 yyextra->currentCmd = cmd;
3184 yyextra->currentMakeEntryType = EntryType::makeCategoryDoc;
3185 BEGIN( CategoryDocArg1 );
3186 return checkStructuralIndicator(yyscanner);
3187}
3188
3189static bool handleUnion(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3190{
3191 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3192 yyextra->currentCmd = cmd;
3193 yyextra->currentMakeEntryType = EntryType::makeUnionDoc;
3194 BEGIN( ClassDocArg1 );
3195 return checkStructuralIndicator(yyscanner);
3196}
3197
3198static bool handleStruct(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3199{
3200 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3201 yyextra->currentCmd = cmd;
3202 yyextra->currentMakeEntryType = EntryType::makeStructDoc;
3203 BEGIN( ClassDocArg1 );
3204 return checkStructuralIndicator(yyscanner);
3205}
3206
3207static bool handleInterface(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3208{
3209 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3210 yyextra->currentCmd = cmd;
3211 yyextra->currentMakeEntryType = EntryType::makeInterfaceDoc;
3212 BEGIN( ClassDocArg1 );
3213 return checkStructuralIndicator(yyscanner);
3214}
3215
3216static bool handleIdlException(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3217{
3218 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3219 yyextra->currentCmd = cmd;
3220 yyextra->currentMakeEntryType = EntryType::makeExceptionDoc;
3221 BEGIN( ClassDocArg1 );
3222 return checkStructuralIndicator(yyscanner);
3223}
3224
3225static bool handlePage(yyscan_t yyscanner,const DString &, const StringVector &)
3226{
3227 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3228 bool stop=makeStructuralIndicator(yyscanner,EntryType::makePageDoc);
3229 BEGIN( PageDocArg1 );
3230 return stop;
3231}
3232
3233static bool handleMainpage(yyscan_t yyscanner,const DString &, const StringVector &)
3234{
3235 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3236 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeMainpageDoc);
3237 if (!stop)
3238 {
3239 yyextra->current->name = "mainpage";
3240 }
3241 setOutput(yyscanner,OutputDoc);
3242 BEGIN( PageDocArg2 );
3243 return stop;
3244}
3245
3246static bool handleFile(yyscan_t yyscanner,const DString &, const StringVector &)
3247{
3248 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3249 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeFileDoc);
3250 if (!stop)
3251 {
3252 yyextra->current->name = yyextra->fileName;
3253 }
3254 BEGIN( FileDocArg1 );
3255 return stop;
3256}
3257
3258static bool handleParam(yyscan_t yyscanner,const DString &, const StringVector &)
3259{
3260 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3261 // we need process param and retval arguments to escape leading underscores in case of
3262 // markdown processing, see bug775493
3263 addOutput(yyscanner,"@param ");
3264 BEGIN( ParamArg1 );
3265 return false;
3266}
3267
3268static bool handleRetval(yyscan_t yyscanner,const DString &, const StringVector &)
3269{
3270 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3271 addOutput(yyscanner,"@retval ");
3272 BEGIN( ParamArg1 );
3273 return false;
3274}
3275
3276static bool handleDir(yyscan_t yyscanner,const DString &, const StringVector &)
3277{
3278 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3279 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeDirDoc);
3280 if (!stop) yyextra->current->name = yyextra->fileName;
3281 BEGIN( FileDocArg1 );
3282 return stop;
3283}
3284
3285static bool handleExample(yyscan_t yyscanner,const DString &cmd, const StringVector &optList)
3286{
3287 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3288 MakeEntryType sectionMaker = EntryType::makeExample;
3289 for (const auto &opt : optList)
3290 {
3291 if (opt=="lineno")
3292 {
3293 sectionMaker=EntryType::makeExampleLineno;
3294 }
3295 else
3296 {
3297 warn(yyextra->fileName,yyextra->lineNr,
3298 "unsupported option '{}' for command '\\{}'",opt,cmd);
3299 }
3300 }
3301 bool stop=makeStructuralIndicator(yyscanner,sectionMaker);
3302 if (!stop) yyextra->current->name = yyextra->fileName;
3303 BEGIN( FileDocArg1 );
3304 return stop;
3305}
3306
3307static bool handleDetails(yyscan_t yyscanner,const DString &, const StringVector &)
3308{
3309 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3310 if (yyextra->inContext!=OutputBrief)
3311 {
3312 addOutput(yyscanner," \\ilinebr\\ilinebr "); // treat @details outside brief description
3313 // as a new paragraph
3314 }
3315 setOutput(yyscanner,OutputDoc);
3316 return false;
3317}
3318
3319static bool handleRaiseWarning(yyscan_t yyscanner,const DString &, const StringVector &)
3320{
3321 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3322 yyextra->raiseWarning = "";
3323 BEGIN( RaiseWarning );
3324 return false;
3325}
3326
3327static bool handleNoop(yyscan_t yyscanner,const DString &, const StringVector &)
3328{
3329 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3330 BEGIN( Noop );
3331 return false;
3332}
3333
3334static bool handleName(yyscan_t yyscanner,const DString &, const StringVector &)
3335{
3336 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3337 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeMemberGrp);
3338 if (!stop)
3339 {
3340 yyextra->docGroup.clearHeader();
3341 BEGIN( NameParam );
3342 if (!yyextra->docGroup.empty()) // end of previous member group
3343 {
3344 yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,true,true);
3345 }
3346 }
3347 return stop;
3348}
3349
3350static bool handleTodo(yyscan_t yyscanner,const DString &, const StringVector &)
3351{
3352 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3353 yyextra->newXRefKind = XRef_Todo;
3354 setOutput(yyscanner,OutputXRef);
3355 yyextra->xrefKind = XRef_Todo;
3356 return false;
3357}
3358
3359static bool handleTest(yyscan_t yyscanner,const DString &, const StringVector &)
3360{
3361 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3362 yyextra->newXRefKind = XRef_Test;
3363 setOutput(yyscanner,OutputXRef);
3364 yyextra->xrefKind = XRef_Test;
3365 return false;
3366}
3367
3368static bool handleBug(yyscan_t yyscanner,const DString &, const StringVector &)
3369{
3370 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3371 yyextra->newXRefKind = XRef_Bug;
3372 setOutput(yyscanner,OutputXRef);
3373 yyextra->xrefKind = XRef_Bug;
3374 return false;
3375}
3376
3377static bool handleDeprecated(yyscan_t yyscanner,const DString &, const StringVector &)
3378{
3379 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3380 yyextra->newXRefKind = XRef_Deprecated;
3381 setOutput(yyscanner,OutputXRef);
3382 yyextra->xrefKind = XRef_Deprecated;
3383 yyextra->current->spec.setDeprDoc(true);
3384 return false;
3385}
3386
3387static bool handleXRefItem(yyscan_t yyscanner,const DString &, const StringVector &)
3388{
3389 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3390 yyextra->newXRefKind = XRef_Item;
3391 BEGIN(XRefItemParam1);
3392 return false;
3393}
3394
3395static bool handleParBlock(yyscan_t yyscanner,const DString &, const StringVector &)
3396{
3397 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3398 if (yyextra->insideParBlock)
3399 {
3400 warn(yyextra->fileName,yyextra->lineNr,
3401 "found \\parblock command while already in a parblock!");
3402 }
3403 if (!yyextra->spaceBeforeCmd.empty())
3404 {
3405 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3406 yyextra->spaceBeforeCmd.clear();
3407 }
3408 addOutput(yyscanner,"@parblock ");
3409 yyextra->insideParBlock = true;
3410 return false;
3411}
3412
3413static bool handleEndParBlock(yyscan_t yyscanner,const DString &, const StringVector &)
3414{
3415 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3416 if (!yyextra->insideParBlock)
3417 {
3418 warn(yyextra->fileName,yyextra->lineNr,
3419 "found \\endparblock command without matching \\parblock!");
3420 }
3421 addOutput(yyscanner,"@endparblock");
3422 setOutput(yyscanner,OutputDoc); // to end a parblock inside a xrefitem like context
3423 yyextra->insideParBlock = false;
3424 return false;
3425}
3426
3427static bool handleRelated(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3428{
3429 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3430 if (!yyextra->current->relates.empty())
3431 {
3432 warn(yyextra->fileName,yyextra->lineNr,
3433 "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
3434 }
3435 yyextra->current->relatesType = RelatesType::Simple;
3436 yyextra->currentCmd = cmd;
3437 BEGIN(RelatesParam1);
3438 return false;
3439}
3440
3441static bool handleRelatedAlso(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3442{
3443 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3444 if (!yyextra->current->relates.empty())
3445 {
3446 warn(yyextra->fileName,yyextra->lineNr,
3447 "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
3448 }
3449 yyextra->current->relatesType = RelatesType::Duplicate;
3450 yyextra->currentCmd = cmd;
3451 BEGIN(RelatesParam1);
3452 return false;
3453}
3454
3455static bool handleMemberOf(yyscan_t yyscanner,const DString &cmd, const StringVector &)
3456{
3457 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3458 if (!yyextra->current->relates.empty())
3459 {
3460 warn(yyextra->fileName,yyextra->lineNr,
3461 "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
3462 }
3463 yyextra->current->relatesType = RelatesType::MemberOf;
3464 yyextra->currentCmd = cmd;
3465 BEGIN(RelatesParam1);
3466 return false;
3467}
3468
3469static bool handleRefItem(yyscan_t yyscanner,const DString &, const StringVector &)
3470{
3471 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3472 addOutput(yyscanner,"@refitem ");
3473 BEGIN(LineParam);
3474 return false;
3475}
3476
3477static bool handleSection(yyscan_t yyscanner,const DString &s, const StringVector &)
3478{
3479 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3480 setOutput(yyscanner,OutputDoc);
3481 //printf("handleSection(%s) raiseLevel=%d\n",qPrint(s),yyextra->raiseLevel);
3482 BEGIN(SectionLabel);
3483 yyextra->sectionLabel.clear();
3484 // determine natural section level
3485 if (s=="section") yyextra->sectionLevel=SectionType::Section;
3486 else if (s=="subsection") yyextra->sectionLevel=SectionType::Subsection;
3487 else if (s=="subsubsection") yyextra->sectionLevel=SectionType::Subsubsection;
3488 else if (s=="paragraph") yyextra->sectionLevel=SectionType::Paragraph;
3489 else if (s=="subparagraph") yyextra->sectionLevel=SectionType::Subparagraph;
3490 else if (s=="subsubparagraph") yyextra->sectionLevel=SectionType::Subsubparagraph;
3491 // raise it if requested
3492 yyextra->sectionLevel = std::min(yyextra->sectionLevel + yyextra->raiseLevel,SectionType::MaxLevel);
3493 // rewrite the update section level to the output
3494 switch (yyextra->sectionLevel)
3495 {
3496 case SectionType::Section: addOutput(yyscanner,"@section "); break;
3497 case SectionType::Subsection: addOutput(yyscanner,"@subsection "); break;
3498 case SectionType::Subsubsection: addOutput(yyscanner,"@subsubsection "); break;
3499 case SectionType::Paragraph: addOutput(yyscanner,"@paragraph "); break;
3500 case SectionType::Subparagraph: addOutput(yyscanner,"@subparagraph "); break;
3501 case SectionType::Subsubparagraph: addOutput(yyscanner,"@subsubparagraph "); break;
3502 default: addOutput(yyscanner,"@"+s+" "); break;
3503 }
3504 return false;
3505}
3506
3507static bool handleRequirement(yyscan_t yyscanner,const DString &s,const StringVector &)
3508{
3509 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3510 bool stop=makeStructuralIndicator(yyscanner,EntryType::makeRequirementDoc);
3511 BEGIN( RequirementLabel );
3512 return stop;
3513}
3514
3515static bool handleSatisfies(yyscan_t yyscanner,const DString &,const StringVector &)
3516{
3517 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3518 BEGIN( SatisfiesLabel );
3519 return false;
3520}
3521
3522static bool handleVerifies(yyscan_t yyscanner,const DString &,const StringVector &)
3523{
3524 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3525 BEGIN( VerifiesLabel );
3526 return false;
3527}
3528
3529static bool handleSubpage(yyscan_t yyscanner,const DString &s, const StringVector &)
3530{
3531 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3532 if (!yyextra->current->section.isEmpty() &&
3533 !yyextra->current->section.isPageDoc() &&
3534 !yyextra->current->section.isMainpageDoc()
3535 )
3536 {
3537 warn(yyextra->fileName,yyextra->lineNr,
3538 "found \\subpage command in a comment block that is not marked as a page!");
3539 }
3540 if (!yyextra->spaceBeforeCmd.empty())
3541 {
3542 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3543 yyextra->spaceBeforeCmd.clear();
3544 }
3545 addOutput(yyscanner,"@"+s+" ");
3546 BEGIN(SubpageLabel);
3547 return false;
3548}
3549
3550static bool handleAnchor(yyscan_t yyscanner,const DString &s, const StringVector &optList)
3551{
3552 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3553 addOutput(yyscanner,"@"+s+" ");
3554 if (optList.empty())
3555 {
3556 yyextra -> anchorTitle = "";
3557 }
3558 else
3559 {
3560 yyextra -> anchorTitle = join(optList," ");
3561 }
3562 BEGIN(AnchorLabel);
3563 return false;
3564}
3565
3566static bool handleImage(yyscan_t yyscanner,const DString &s, const StringVector &optList)
3567{
3568 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3569 for (const auto &opt : optList)
3570 {
3571 DString locOpt(opt);
3572 locOpt = locOpt.stripWhiteSpace();
3573 if (locOpt.lower().startsWith("anchor:"))
3574 {
3575 addAnchor(yyscanner,locOpt.mid(7));
3576 break; // real option handling will be done later on
3577 }
3578 }
3579 if (optList.empty())
3580 {
3581 addOutput(yyscanner,"@"+s+" ");
3582 }
3583 else
3584 {
3585 addOutput(yyscanner,"@"+s+"{"+DString(join(optList,","))+"} ");
3586 }
3587 BEGIN(Comment);
3588 return false;
3589}
3590
3591static bool handleCite(yyscan_t yyscanner,const DString &s, const StringVector &optList)
3592{
3593 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3594 if (!yyextra->spaceBeforeCmd.empty())
3595 {
3596 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3597 yyextra->spaceBeforeCmd.clear();
3598 }
3599 if (optList.empty())
3600 {
3601 addOutput(yyscanner,"@"+s+" ");
3602 }
3603 else
3604 {
3605 addOutput(yyscanner,"@"+s+"{"+DString(join(optList,","))+"} ");
3606 }
3607 BEGIN(CiteLabel);
3608 return false;
3609}
3610
3611static bool handleFormatBlock(yyscan_t yyscanner,const DString &s, const StringVector &optList)
3612{
3613 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3614 if (!yyextra->spaceBeforeCmd.empty())
3615 {
3616 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3617 yyextra->spaceBeforeCmd.clear();
3618 }
3619 if (s=="mermaid")
3620 {
3622 }
3623 if (optList.empty())
3624 {
3625 addOutput(yyscanner,"@"+s+" ");
3626 }
3627 else
3628 {
3629 addOutput(yyscanner,"@"+s+"{"+DString(join(optList,","))+"} ");
3630 }
3631 //printf("handleFormatBlock(%s) with option(%s)\n",qPrint(s),qPrint(opt));
3632 yyextra->blockName=s;
3633 yyextra->commentCount=0;
3634 BEGIN(FormatBlock);
3635 return false;
3636}
3637
3638static bool handleMermaidFile(yyscan_t yyscanner,const DString &s,const StringVector &)
3639{
3640 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3642 addOutput(yyscanner,yytext);
3643 return false;
3644}
3645
3646static bool handleAddIndex(yyscan_t yyscanner,const DString &, const StringVector &)
3647{
3648 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3649 addOutput(yyscanner,yytext);
3650 BEGIN(LineParam);
3651 return false;
3652}
3653
3654static bool handleFileInfo(yyscan_t yyscanner,const DString &cmdName, const StringVector &optList)
3655{
3656 return handleFileInfoResult(yyscanner,cmdName, optList, false);
3657}
3658static bool handleFileInfoSection(yyscan_t yyscanner,const DString &cmdName, const StringVector &optList)
3659{
3660 return handleFileInfoResult(yyscanner,cmdName, optList, true);
3661}
3662
3663static DString fileInfoLookup(const FileInfo &fi,const std::string &optionName)
3664{
3665 using OptionFunc = std::function<DString(const FileInfo &)>;
3666 static std::unordered_map<std::string,OptionFunc> options =
3667 {
3668 // name, function producing the value
3669 { "name", [](const FileInfo &fi_) -> DString { return fi_.baseName(); } },
3670 { "extension", [](const FileInfo &fi_) -> DString { return fi_.extension(true); } },
3671 { "filename", [](const FileInfo &fi_) -> DString { return fi_.fileName(); } },
3672 { "directory", [](const FileInfo &fi_) -> DString { return fi_.dirPath(); } },
3673 { "full", [](const FileInfo &fi_) -> DString { return fi_.absFilePath(); } }
3674 };
3675 auto it = options.find(optionName);
3676 return (it!=options.end()) ? it->second(fi) : DString();
3677}
3678
3679static bool handleFileInfoResult(yyscan_t yyscanner,const DString &, const StringVector &optList, bool isSection)
3680{
3681 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3682 if (!yyextra->spaceBeforeCmd.empty())
3683 {
3684 if (isSection) yyextra->sectionTitle+=yyextra->spaceBeforeCmd;
3685 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3686 yyextra->spaceBeforeCmd.clear();
3687 }
3688 bool first = true;
3689 FileInfo fi(yyextra->fileName.str());
3690 for (const auto &opt_ : optList)
3691 {
3692 DString optStripped = DString(opt_).stripWhiteSpace();
3693 std::string opt = optStripped.lower().str();
3694 DString result = fileInfoLookup(fi,opt);
3695 if (!result.empty())
3696 {
3697 if (!first)
3698 {
3699 warn(yyextra->fileName,yyextra->lineNr,"Multiple options specified with \\fileinfo, discarding '{}'", optStripped);
3700 }
3701 else
3702 {
3703 addOutput(yyscanner,result);
3704 if (isSection)
3705 {
3706 yyextra->sectionTitle+=result;
3707 }
3708 }
3709 first = false;
3710 }
3711 else
3712 {
3713 warn(yyextra->fileName,yyextra->lineNr,"Unknown option specified with \\fileinfo: '{}'", optStripped);
3714 }
3715 }
3716 if (first) // no options specified
3717 {
3718 if (Config_getBool(FULL_PATH_NAMES))
3719 {
3720 if (isSection) yyextra->sectionTitle+=stripFromPath(yyextra->fileName);
3721 addOutput(yyscanner,stripFromPath(yyextra->fileName));
3722 }
3723 else
3724 {
3725 if (isSection) yyextra->sectionTitle+=yyextra->fileName;
3726 addOutput(yyscanner,yyextra->fileName);
3727 }
3728 }
3729 return false;
3730}
3731
3732static bool handleLineInfo(yyscan_t yyscanner,const DString &, const StringVector &)
3733{
3734 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3735 if (!yyextra->spaceBeforeCmd.empty())
3736 {
3737 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3738 yyextra->spaceBeforeCmd.clear();
3739 }
3740 addOutput(yyscanner,DString().setNum(yyextra->lineNr));
3741 return false;
3742}
3743
3744static bool handleILine(yyscan_t yyscanner,const DString &, const StringVector &)
3745{
3746 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3747 addOutput(yyscanner,yytext);
3748 BEGIN(ILine);
3749 return false;
3750}
3751
3752static bool handleIFile(yyscan_t yyscanner,const DString &, const StringVector &)
3753{
3754 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3755 addOutput(yyscanner,yytext);
3756 BEGIN(IFile);
3757 return false;
3758}
3759
3760static bool handleIRaise(yyscan_t yyscanner,const DString &, const StringVector &)
3761{
3762 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3763 BEGIN(IRaise);
3764 return false;
3765}
3766
3767static bool handleIPrefix(yyscan_t yyscanner,const DString &, const StringVector &)
3768{
3769 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3770 addOutput(yyscanner,"@iprefix ");
3771 BEGIN(IRaisePrefix);
3772 return false;
3773}
3774
3775static bool handleIf(yyscan_t yyscanner,const DString &, const StringVector &)
3776{
3777 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3778 yyextra->guardType = Guard_If;
3779 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
3780 if (yyextra->guards->empty())
3781 {
3782 yyextra->guards->emplace(true);
3783 }
3784 else
3785 {
3786 bool enabled = yyextra->guards->top().isEnabled();
3787 yyextra->guards->emplace(enabled);
3788 }
3789 BEGIN(GuardParam);
3790 return false;
3791}
3792
3793static bool handleIfNot(yyscan_t yyscanner,const DString &, const StringVector &)
3794{
3795 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3796 yyextra->guardType = Guard_IfNot;
3797 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
3798 if (yyextra->guards->empty())
3799 {
3800 yyextra->guards->emplace(true);
3801 }
3802 else
3803 {
3804 bool enabled = yyextra->guards->top().isEnabled();
3805 yyextra->guards->emplace(enabled);
3806 }
3807 BEGIN(GuardParam);
3808 return false;
3809}
3810
3811static bool handleElseIf(yyscan_t yyscanner,const DString &, const StringVector &)
3812{
3813 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3814 if (yyextra->guards->empty())
3815 {
3816 warn(yyextra->fileName,yyextra->lineNr,
3817 "found \\elseif without matching start command");
3818 }
3819 else if (yyextra->guards->top().hasElse())
3820 {
3821 warn(yyextra->fileName,yyextra->lineNr,
3822 "found \\elseif command after \\else command was given in \\if construct");
3823 yyextra->guardType = Guard_ElseIf;
3824 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
3825 yyextra->guards->top().setEnabled(false);
3826 BEGIN(GuardParam);
3827 }
3828 else
3829 {
3830 yyextra->guardType = Guard_ElseIf;
3831 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
3832 yyextra->guards->top().setEnabled(false);
3833 BEGIN(GuardParam);
3834 }
3835 return false;
3836}
3837
3838static bool handleElse(yyscan_t yyscanner,const DString &, const StringVector &)
3839{
3840 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3841 if (yyextra->guards->empty())
3842 {
3843 warn(yyextra->fileName,yyextra->lineNr,
3844 "found \\else without matching start command");
3845 }
3846 else if (yyextra->guards->top().hasElse())
3847 {
3848 warn(yyextra->fileName,yyextra->lineNr,
3849 "found multiple \\else commands in same \\if construct");
3850 yyextra->guards->top().setEnabled(false);
3851 yyextra->guards->top().setElse();
3852 BEGIN( SkipGuardedSection );
3853 }
3854 else
3855 {
3856 yyextra->guards->top().setElse();
3857 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
3858 if (yyextra->guards->top().isEnabledFound())
3859 {
3860 yyextra->guards->top().setEnabled(false);
3861 BEGIN( SkipGuardedSection );
3862 }
3863 else
3864 {
3865 yyextra->guards->top().setEnabled(true);
3866 BEGIN( GuardParamEnd );
3867 }
3868 }
3869 return false;
3870}
3871
3872static bool handleEndIf(yyscan_t yyscanner,const DString &, const StringVector &)
3873{
3874 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3875 if (yyextra->guards->empty())
3876 {
3877 warn(yyextra->fileName,yyextra->lineNr,
3878 "found \\endif without matching start command");
3879 }
3880 else
3881 {
3882 yyextra->guards->pop();
3883 }
3884 if (!yyextra->spaceBeforeCmd.empty())
3885 {
3886 addOutput(yyscanner,yyextra->spaceBeforeCmd);
3887 yyextra->spaceBeforeCmd.clear();
3888 }
3889 if (yyextra->guards->empty())
3890 {
3891 BEGIN( GuardParamEnd );
3892 }
3893 else
3894 {
3895 if (yyextra->guards->top().isEnabled())
3896 {
3897 BEGIN( GuardParamEnd );
3898 }
3899 else
3900 {
3901 BEGIN( SkipGuardedSection );
3902 }
3903 }
3904 return false;
3905}
3906
3907static bool handleIngroup(yyscan_t yyscanner,const DString &, const StringVector &)
3908{
3909 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3910 yyextra->inGroupParamFound=false;
3911 BEGIN( InGroupParam );
3912 return false;
3913}
3914
3915static bool handleNoSubGrouping(yyscan_t yyscanner,const DString &, const StringVector &)
3916{
3917 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3918 yyextra->current->subGrouping = false;
3919 return false;
3920}
3921
3922static bool handleShowInitializer(yyscan_t yyscanner,const DString &, const StringVector &)
3923{
3924 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3925 yyextra->current->initLines = 100000; // ON
3926 return false;
3927}
3928
3929static bool handleHideInitializer(yyscan_t yyscanner,const DString &, const StringVector &)
3930{
3931 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3932 yyextra->current->initLines = 0; // OFF
3933 return false;
3934}
3935
3936static bool handleCallgraph(yyscan_t yyscanner,const DString &, const StringVector &)
3937{
3938 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3939 yyextra->current->commandOverrides.override_callGraph(true); // ON
3940 return false;
3941}
3942
3943static bool handleHideCallgraph(yyscan_t yyscanner,const DString &, const StringVector &)
3944{
3945 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3946 yyextra->current->commandOverrides.override_callGraph(false); // OFF
3947 return false;
3948}
3949
3950static bool handleCallergraph(yyscan_t yyscanner,const DString &, const StringVector &)
3951{
3952 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3953 yyextra->current->commandOverrides.override_callerGraph(true); // ON
3954 return false;
3955}
3956
3957static bool handleHideCallergraph(yyscan_t yyscanner,const DString &, const StringVector &)
3958{
3959 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3960 yyextra->current->commandOverrides.override_callerGraph(false); // OFF
3961 return false;
3962}
3963
3964static bool handleShowEnumValues(yyscan_t yyscanner,const DString &, const StringVector &)
3965{
3966 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3967 yyextra->current->commandOverrides.override_enumValues(true); // ON
3968 return false;
3969}
3970
3971static bool handleHideEnumValues(yyscan_t yyscanner,const DString &, const StringVector &)
3972{
3973 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3974 yyextra->current->commandOverrides.override_enumValues(false); // OFF
3975 return false;
3976}
3977
3978static bool handleShowInlineSource(yyscan_t yyscanner,const DString &, const StringVector &)
3979{
3980 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3981 yyextra->current->commandOverrides.override_inlineSource(true); // ON
3982 return false;
3983}
3984
3985static bool handleHideInlineSource(yyscan_t yyscanner,const DString &, const StringVector &)
3986{
3987 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3988 yyextra->current->commandOverrides.override_inlineSource(false); // OFF
3989 return false;
3990}
3991
3992static bool handleIncludegraph(yyscan_t yyscanner,const DString &, const StringVector &)
3993{
3994 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3995 yyextra->current->commandOverrides.override_includeGraph(true); // ON
3996 return false;
3997}
3998
3999static bool handleIncludedBygraph(yyscan_t yyscanner,const DString &, const StringVector &)
4000{
4001 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4002 yyextra->current->commandOverrides.override_includedByGraph(true); // ON
4003 return false;
4004}
4005
4006static bool handleHideIncludegraph(yyscan_t yyscanner,const DString &, const StringVector &)
4007{
4008 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4009 yyextra->current->commandOverrides.override_includeGraph(false); // OFF
4010 return false;
4011}
4012
4013static bool handleHideIncludedBygraph(yyscan_t yyscanner,const DString &, const StringVector &)
4014{
4015 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4016 yyextra->current->commandOverrides.override_includedByGraph(false); // OFF
4017 return false;
4018}
4019
4020static bool handleDirectoryGraph(yyscan_t yyscanner,const DString &, const StringVector &)
4021{
4022 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4023 yyextra->current->commandOverrides.override_directoryGraph(true); // ON
4024 return false;
4025}
4026
4027static bool handleHideDirectoryGraph(yyscan_t yyscanner,const DString &, const StringVector &)
4028{
4029 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4030 yyextra->current->commandOverrides.override_directoryGraph(false); // OFF
4031 return false;
4032}
4033
4034static bool handleCollaborationgraph(yyscan_t yyscanner,const DString &, const StringVector &)
4035{
4036 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4037 yyextra->current->commandOverrides.override_collaborationGraph(true); // ON
4038 return false;
4039}
4040
4041static bool handleHideCollaborationgraph(yyscan_t yyscanner,const DString &, const StringVector &)
4042{
4043 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4044 yyextra->current->commandOverrides.override_collaborationGraph(false); // OFF
4045 return false;
4046}
4047
4048static bool handleGroupgraph(yyscan_t yyscanner,const DString &, const StringVector &)
4049{
4050 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4051 yyextra->current->commandOverrides.override_groupGraph(true); // ON
4052 return false;
4053}
4054
4055static bool handleHideGroupgraph(yyscan_t yyscanner,const DString &, const StringVector &)
4056{
4057 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4058 yyextra->current->commandOverrides.override_groupGraph(false); // OFF
4059 return false;
4060}
4061
4062static bool handleInheritanceGraph(yyscan_t yyscanner,const DString &, const StringVector &optList)
4063{
4064 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4065 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::YES);
4066 for (const auto &opt_ : optList)
4067 {
4068 DString opt = DString(opt_).stripWhiteSpace().lower();
4069 if (!opt.empty())
4070 {
4071 if (opt == "yes")
4072 {
4073 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::YES);
4074 }
4075 else if (opt == "graph")
4076 {
4077 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::GRAPH);
4078 }
4079 else if (opt == "builtin")
4080 {
4081 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::BUILTIN);
4082 }
4083 else if (opt == "text")
4084 {
4085 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::TEXT);
4086 }
4087 else if (opt == "no")
4088 {
4089 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::NO);
4090 }
4091 else
4092 {
4093 warn(yyextra->fileName,yyextra->lineNr,"Unknown option specified with \\inheritancegraph: '{}'",
4094 DString(opt_).stripWhiteSpace());
4095 }
4096 }
4097 }
4098 return false;
4099}
4100
4101static bool handleHideInheritanceGraph(yyscan_t yyscanner,const DString &, const StringVector &)
4102{
4103 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4104 yyextra->current->commandOverrides.override_inheritanceGraph(CLASS_GRAPH_t::NO); // OFF
4105 return false;
4106}
4107
4108static bool handleReferencedByRelation(yyscan_t yyscanner,const DString &, const StringVector &)
4109{
4110 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4111 yyextra->current->commandOverrides.override_referencedByRelation(true); // ON
4112 return false;
4113}
4114
4115static bool handleHideReferencedByRelation(yyscan_t yyscanner,const DString &, const StringVector &)
4116{
4117 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4118 yyextra->current->commandOverrides.override_referencedByRelation(false); // OFF
4119 return false;
4120}
4121
4122static bool handleReferencesRelation(yyscan_t yyscanner,const DString &, const StringVector &)
4123{
4124 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4125 yyextra->current->commandOverrides.override_referencesRelation(true); // ON
4126 return false;
4127}
4128
4129static bool handleHideReferencesRelation(yyscan_t yyscanner,const DString &, const StringVector &)
4130{
4131 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4132 yyextra->current->commandOverrides.override_referencesRelation(false); // OFF
4133 return false;
4134}
4135
4136static bool handleQualifier(yyscan_t yyscanner,const DString &cmd, const StringVector &)
4137{
4138 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4139 yyextra->currentCmd = cmd;
4140 BEGIN(Qualifier);
4141 return false;
4142}
4143
4144static bool handleInternal(yyscan_t yyscanner,const DString &, const StringVector &)
4145{
4146 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4147 if (!Config_getBool(INTERNAL_DOCS))
4148 {
4149 // make sure some whitespace before a \internal command
4150 // is not treated as "documentation"
4151 if (yyextra->current->doc.stripWhiteSpace().empty())
4152 {
4153 yyextra->current->doc.clear();
4154 }
4155 yyextra->condCount=0;
4156 BEGIN( SkipInternal );
4157 }
4158 else
4159 {
4160 // re-enabled for bug640828
4161 addOutput(yyscanner," \\internal ");
4162 yyextra->inInternalDocs = true;
4163 }
4164 return false;
4165}
4166
4167static bool handleStatic(yyscan_t yyscanner,const DString &, const StringVector &)
4168{
4169 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4170 yyextra->current->isStatic = true;
4171 return false;
4172}
4173
4174static bool handlePure(yyscan_t yyscanner,const DString &, const StringVector &)
4175{
4176 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4177 yyextra->current->virt = Specifier::Pure;
4178 return false;
4179}
4180
4181static bool handlePrivate(yyscan_t yyscanner,const DString &, const StringVector &)
4182{
4183 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4184 yyextra->current->protection = Protection::Private;
4185 return false;
4186}
4187
4188static bool handlePrivateSection(yyscan_t yyscanner,const DString &, const StringVector &)
4189{
4190 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4191 yyextra->current->protection = yyextra->protection = Protection::Private;
4192 return false;
4193}
4194
4195static bool handleProtected(yyscan_t yyscanner,const DString &, const StringVector &)
4196{
4197 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4198 yyextra->current->protection = Protection::Protected;
4199 return false;
4200}
4201
4202static bool handleProtectedSection(yyscan_t yyscanner,const DString &, const StringVector &)
4203{
4204 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4205 yyextra->current->protection = yyextra->protection = Protection::Protected ;
4206 return false;
4207}
4208
4209static bool handlePublic(yyscan_t yyscanner,const DString &, const StringVector &)
4210{
4211 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4212 yyextra->current->protection = Protection::Public;
4213 return false;
4214}
4215
4216static bool handlePublicSection(yyscan_t yyscanner,const DString &, const StringVector &)
4217{
4218 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4219 yyextra->current->protection = yyextra->protection = Protection::Public;
4220 return false;
4221}
4222
4223static bool handleToc(yyscan_t yyscanner,const DString &, const StringVector &optList)
4224{
4225 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4226 if (yyextra->current->section.isPageDoc() ||
4227 yyextra->current->section.isMainpageDoc())
4228 {
4229 for (const auto &opt_ : optList)
4230 {
4231 DString opt = DString(opt_).stripWhiteSpace().lower();
4232 int level = SectionType::MaxLevel;
4233 size_t i = opt.find(':');
4234 if (i!=DString::npos && i>0) // found ':' but not on position 0 what would mean just a level
4235 {
4236 char dum=0;
4237 if (sscanf(opt.mid(i+1).data(),"%d%c",&level,&dum) != 1)
4238 {
4239 warn(yyextra->fileName,yyextra->lineNr,"Unknown option:level specified with \\tableofcontents: '{}'",
4240 qPrint(DString(opt_).stripWhiteSpace()));
4241 opt = "";
4242 }
4243 else
4244 {
4245 level = level<=0 ? SectionType::MaxLevel : std::min(level,SectionType::MaxLevel);
4246 opt = opt.left(i).stripWhiteSpace();
4247 }
4248 }
4249 if (!opt.empty())
4250 {
4251 if (opt == "html")
4252 {
4253 yyextra->current->localToc.enableHtml(level);
4254 }
4255 else if (opt == "latex")
4256 {
4257 yyextra->current->localToc.enableLatex(level);
4258 }
4259 else if (opt == "xml")
4260 {
4261 yyextra->current->localToc.enableXml(level);
4262 }
4263 else if (opt == "docbook")
4264 {
4265 yyextra->current->localToc.enableDocbook(level);
4266 }
4267 else
4268 {
4269 warn(yyextra->fileName,yyextra->lineNr,"Unknown option specified with \\tableofcontents: '{}'",
4270 DString(opt_).stripWhiteSpace());
4271 }
4272 }
4273 }
4274 if (yyextra->current->localToc.nothingEnabled())
4275 {
4276 // for backward compatibility
4277 yyextra->current->localToc.enableHtml(SectionType::MaxLevel);
4278 yyextra->current->localToc.enableXml(SectionType::MaxLevel);
4279 }
4280 }
4281 return false;
4282}
4283
4284static bool handleInherit(yyscan_t yyscanner,const DString &, const StringVector &)
4285{
4286 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4287 BEGIN(InheritParam);
4288 return false;
4289}
4290
4291static bool handleExtends(yyscan_t yyscanner,const DString &cmd, const StringVector &)
4292{
4293 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4294 yyextra->currentCmd = cmd;
4295 BEGIN(ExtendsParam);
4296 return false;
4297}
4298
4299static bool handleCopyBrief(yyscan_t yyscanner,const DString &, const StringVector &)
4300{
4301 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4302 if (yyextra->current->brief.stripWhiteSpace().empty() && yyextra->current->doc.stripWhiteSpace().empty())
4303 { // if we don't have a brief or detailed description yet,
4304 // then the @copybrief should end up in the brief description.
4305 // otherwise it will be copied inline (see bug691315 & bug700788)
4306 setOutput(yyscanner,OutputBrief);
4307 }
4308 if (!yyextra->spaceBeforeCmd.empty())
4309 {
4310 addOutput(yyscanner,yyextra->spaceBeforeCmd);
4311 yyextra->spaceBeforeCmd.clear();
4312 }
4313 addOutput(yyscanner,"\\copybrief ");
4314 return false;
4315}
4316
4317static bool handleCopyDetails(yyscan_t yyscanner,const DString &, const StringVector &)
4318{
4319 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4320 setOutput(yyscanner,OutputDoc);
4321 if (!yyextra->spaceBeforeCmd.empty())
4322 {
4323 addOutput(yyscanner,yyextra->spaceBeforeCmd);
4324 yyextra->spaceBeforeCmd.clear();
4325 }
4326 addOutput(yyscanner,"\\copydetails ");
4327 return false;
4328}
4329
4330static bool handleCopyDoc(yyscan_t yyscanner,const DString &, const StringVector &)
4331{
4332 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4333 if (yyextra->current->brief.stripWhiteSpace().empty() && yyextra->current->doc.stripWhiteSpace().empty())
4334 { // if we don't have a brief or detailed description yet,
4335 // then the @copybrief should end up in the brief description.
4336 // otherwise it will be copied inline (see bug691315 & bug700788)
4337 setOutput(yyscanner,OutputBrief);
4338 }
4339 if (!yyextra->spaceBeforeCmd.empty())
4340 {
4341 addOutput(yyscanner,yyextra->spaceBeforeCmd);
4342 yyextra->spaceBeforeCmd.clear();
4343 }
4344 addOutput(yyscanner,"\\copybrief ");
4345 yyextra->copyDocArg.clear();
4346 yyextra->braceCount = 0;
4347 BEGIN(CopyDoc);
4348 return false;
4349}
4350
4351//-----------------------------------------------------------------------------------------
4352
4353static void initParser(yyscan_t yyscanner)
4354{
4355 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4356 yyextra->sectionLabel.clear();
4357 yyextra->sectionTitle.clear();
4358 yyextra->docGroup.clearHeader();
4359 yyextra->insideParBlock = false;
4360}
4361
4362//-----------------------------------------------------------------------------
4363
4365{
4366 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4367 //printf("yyextra->current->section=%x\n",yyextra->current->section);
4368 return yyextra->current->section.isDoc();
4369}
4370
4372{
4373 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4374 assert(maker!=nullptr); // detect programming error
4375 //printf("yyextra->current->section=%x\n",yyextra->current->section);
4376 if (yyextra->current->section.isDoc())
4377 {
4378 return true;
4379 }
4380 else if (maker)
4381 {
4382 yyextra->needNewEntry = true;
4383 yyextra->current->section = maker();
4384 yyextra->current->fileName = yyextra->fileName;
4385 yyextra->current->startLine = yyextra->lineNr;
4386 if (yyextra->current->docLine == -1) yyextra->current->docLine = yyextra->lineNr;
4387 return false;
4388 }
4389 else
4390 {
4391 return false;
4392 }
4393}
4394
4395//-----------------------------------------------------------------
4396
4397static void lineCount(yyscan_t yyscanner)
4398{
4399 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4400 for( const char* c = yytext ; *c ; ++c )
4401 yyextra->lineNr += (*c == '\n') ;
4402}
4403
4404//-----------------------------------------------------------------
4405
4406static DString stripQuotes(const char *s)
4407{
4408 DString name;
4409 if (s==nullptr || *s==0) return name;
4410 name=s;
4411 if (name.at(0)=='"' && name.at(name.length()-1)=='"')
4412 {
4413 name=name.mid(1,name.length()-2);
4414 }
4415 return name;
4416}
4417
4418//-----------------------------------------------------------------
4419
4420static void addRequirementId(yyscan_t yyscanner)
4421{
4422 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4423 std::unique_lock<std::mutex> lock(g_sectionMutex);
4424
4425 DString reqId = yyextra->current->name;
4426 //printf("### add reqId='%s' reqTitle='%s'\n",qPrint(reqId),qPrint(yyextra->current->type));
4428 const SectionInfo *si = sm.find(reqId);
4429 if (si==nullptr)
4430 {
4431 si = sm.add(reqId,"requirements",yyextra->lineNr,
4432 yyextra->current->type,SectionType::Requirement,1);
4433 }
4434 else // duplicate requirement
4435 {
4436 warn(yyextra->fileName,yyextra->lineNr,"duplicate requirement ID '{}' found at {} line {}, (first occurrence: {}, line {})",
4437 reqId,
4438 yyextra->fileName,yyextra->lineNr,
4439 si->fileName(),si->lineNr());
4440 }
4441}
4442
4443//-----------------------------------------------------------------
4444
4445static void addXRefItemToEntry(Entry *current, const DString &docs,
4446 const DString &listName,const DString &itemTitle,
4447 const DString &listTitle,bool append,bool inBody,int lineNr)
4448{
4449 if (listName.empty()) return;
4450 //printf("addXRefItem(listName=%s,itemTitle=%s,listTitle=%s,append=%d,inbody=%d)\n",
4451 // qPrint(listName),qPrint(itemTitle),qPrint(listTitle),append,inBody);
4452
4453 std::unique_lock<std::mutex> lock(g_sectionMutex);
4454
4455 RefList *refList = RefListManager::instance().add(listName,listTitle,itemTitle);
4456 RefItem *item = nullptr;
4457 for (auto it = current->sli.rbegin(); it != current->sli.rend(); ++it)
4458 {
4459 RefItem *i = *it;
4460 if (i && i->list()->listName()==listName)
4461 {
4462 //printf("found %s lii->type=%s\n",listName,qPrint(i->list()->listName()));
4463 item = i;
4464 break;
4465 }
4466 }
4467 if (item && append) // already found item of same type just before this one
4468 {
4469 //printf("listName=%s item id = %d existing\n",listName,item->id());
4470 item->setText(item->text() + " <p>" + docs);
4471 //printf("%s: text +=%s\n",listName,qPrint(item->text));
4472 }
4473 else // new item
4474 {
4475 // if we have already an item from the same list type (e.g. a second @todo)
4476 // in the same Entry (i.e. lii!=0) then we reuse its link anchor.
4477 item = refList->add();
4478 //printf("listName=%s item id = %d new yyextra->current=%p\n",listName,item->id(),yyextra->current);
4479 DString anchorLabel;
4480 anchorLabel.sprintf("_%s%06d",listName.data(),item->id());
4481 item->setText(docs);
4482 item->setAnchor(anchorLabel);
4483 current->sli.push_back(item);
4484 DString cmdString;
4485 cmdString.sprintf("\\ilinebr \\xrefitem %s %d.",qPrint(listName),item->id());
4486 if (inBody)
4487 {
4488 current->inbodyDocs += cmdString;
4489 }
4490 else
4491 {
4492 current->doc += cmdString;
4493 }
4494
4495 {
4497 const SectionInfo *si = sm.find(anchorLabel);
4498 if (si)
4499 {
4500 if (!si->ref().empty()) // we are from a tag file
4501 {
4502 si = sm.replace(anchorLabel,listName,lineNr,"",SectionType::Anchor,0);
4503 current->anchors.push_back(si);
4504 }
4505 else if (si->lineNr() != -1)
4506 {
4507 warn(listName,lineNr,"multiple use of section label '{}', (first occurrence: {}, line {})",
4508 anchorLabel,si->fileName(),si->lineNr());
4509 }
4510 else
4511 {
4512 warn(listName,lineNr,"multiple use of section label '{}', (first occurrence: {})",
4513 anchorLabel,si->fileName());
4514 }
4515 }
4516 else
4517 {
4518 si = sm.add(anchorLabel,listName,lineNr,"",SectionType::Anchor,0);
4519 current->anchors.push_back(si);
4520 }
4521 }
4522 }
4523}
4524
4525//-----------------------------------------------------------------------------
4526
4527static void addXRefItem(yyscan_t yyscanner,
4528 const DString &listName,const DString &itemTitle,
4529 const DString &listTitle,bool append)
4530{
4531 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4532 addXRefItemToEntry(yyextra->current,yyextra->outputXRef,listName,itemTitle,listTitle,append,yyextra->inBody,yyextra->lineNr);
4533 yyextra->outputXRef.clear();
4534}
4535
4536//-----------------------------------------------------------------------------
4537
4538// make label match LABELID pattern
4539static void escapeLabel(DString &label)
4540{
4541 if (label.empty()) return;
4542 char c = label[0];
4543 if (!((c>='a' && c<='z') || (c>='A' && c<='Z') || c=='_' || c<0))
4544 {
4545 label[0]='_'; // replace invalid starting char by _
4546 }
4547 for (size_t i=1; i<label.size(); i++)
4548 {
4549 c = label[i];
4550 if (!((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_' || c<0))
4551 {
4552 label[i]='_'; // replace invalid char by _
4553 }
4554 }
4555}
4556
4557
4558//-----------------------------------------------------------------------------
4559
4560// Adds a formula text to the list/dictionary of formulas if it was
4561// not already added. Returns the label of the formula.
4562static DString addFormula(yyscan_t yyscanner)
4563{
4564 std::unique_lock<std::mutex> lock(g_formulaMutex);
4565 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4566 DString formLabel;
4567 DString formula = (yyextra->formulaPreText +
4568 yyextra->formulaText.stripLeadingAndTrailingEmptyLines() +
4569 yyextra->formulaPostText).stripWhiteSpace();
4570 //printf("formulaText=\n=1=\n{%s}\n=2=\n{%s}\n=3=\n{%s}\n===",
4571 // qPrint(yyextra->formulaText),
4572 // qPrint(yyextra->formulaText.stripLeadingAndTrailingEmptyLines()),
4573 // qPrint(formula)
4574 // );
4575 int id = FormulaManager::instance().addFormula(formula);
4576 formLabel.sprintf("\\_form#%d",id);
4577 for (int i=0;i<yyextra->formulaNewLines;i++) formLabel+="@_fakenl"; // add fake newlines to
4578 // keep the warnings
4579 // correctly aligned.
4580 return formLabel;
4581}
4582
4583//-----------------------------------------------------------------------------
4584
4586{
4587 if (level>=0 && level<SectionType::MaxLevel) return SectionType(level);
4588 return SectionType::Anchor;
4589}
4590
4591static void addSection(yyscan_t yyscanner, bool addYYtext)
4592{
4593 std::unique_lock<std::mutex> lock(g_sectionMutex);
4594 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4596 const SectionInfo *si = sm.find(yyextra->sectionLabel);
4597 if (si)
4598 {
4599 if (!si->ref().empty()) // we are from a tag file
4600 {
4601 // create a new section element
4602 if (addYYtext) yyextra->sectionTitle+=yytext;
4603 yyextra->sectionTitle=yyextra->sectionTitle.stripWhiteSpace();
4604 si = sm.replace(yyextra->sectionLabel,yyextra->fileName,yyextra->lineNr,
4605 yyextra->sectionTitle,sectionLevelToType(yyextra->sectionLevel),
4606 yyextra->sectionLevel);
4607
4608 // add section to this entry
4609 yyextra->current->anchors.push_back(si);
4610 }
4611 else if (si->lineNr() != -1)
4612 {
4613 warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '{}' while adding section, (first occurrence: {}, line {})",
4614 yyextra->sectionLabel,si->fileName(),si->lineNr());
4615 }
4616 else
4617 {
4618 warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '{}' while adding section, (first occurrence: {})",
4619 yyextra->sectionLabel,si->fileName());
4620 }
4621 }
4622 else
4623 {
4624 // create a new section element
4625 if (addYYtext) yyextra->sectionTitle+=yytext;
4626 yyextra->sectionTitle=yyextra->sectionTitle.stripWhiteSpace();
4627 si = sm.add(yyextra->sectionLabel,yyextra->fileName,yyextra->lineNr,
4628 yyextra->sectionTitle,sectionLevelToType(yyextra->sectionLevel),
4629 yyextra->sectionLevel);
4630
4631 // add section to this entry
4632 yyextra->current->anchors.push_back(si);
4633 }
4634}
4635
4636//-----------------------------------------------------------------------------
4637
4638static void addCite(yyscan_t yyscanner)
4639{
4640 std::unique_lock<std::mutex> lock(g_citeMutex);
4641 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4642 DString name(yytext);
4643 if (yytext[0] =='"')
4644 {
4645 name=yytext+1;
4646 name=name.left((int)yyleng-2);
4647 }
4649}
4650
4651//-----------------------------------------------------------------------------
4652static const reg::Ex nonBrief_re(R"( *[\\@]ifile \"[^\"]*\" [\\@]iline (\d+) [\\@]ilinebr ([ \n]*))");
4653
4654// strip trailing whitespace (excluding newlines) from string s
4656{
4657 size_t len = s.length();
4658 int i = (int)len-1;
4659 while (i>=0)
4660 {
4661 char c = s.at(i);
4662 if (c==' ' || c=='\t' || c=='\r') // normal whitespace
4663 {
4664 i--;
4665 }
4666 else if (c=='r' && i>=7 && literal_at(s.data()+i-7,"\\ilinebr")) // special line break marker
4667 {
4668 i-=8;
4669 }
4670 else // non-whitespace
4671 {
4672 break;
4673 }
4674 }
4675 //printf("stripTrailingWhitespace(%s) i=%d len=%d\n",qPrint(s),i,len);
4676 if (i!=(int)len-1)
4677 {
4678 s.resize(i+1); // string up to and including char at pos i
4679 }
4680}
4681
4682// selects the output to write to
4683static inline void setOutput(yyscan_t yyscanner,OutputContext ctx)
4684{
4685 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4686 bool xrefAppendToPrev = yyextra->xrefAppendFlag;
4687 // determine append flag for the next item (i.e. the end of this item)
4688 yyextra->xrefAppendFlag = !yyextra->inBody &&
4689 yyextra->inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items
4690 yyextra->newXRefKind==yyextra->xrefKind && // of the same kind
4691 (yyextra->xrefKind!=XRef_Item ||
4692 yyextra->newXRefItemKey==yyextra->xrefItemKey); // with the same key if \xrefitem
4693 //printf("%d && %d && %d && (%d || %d)\n",
4694 // yyextra->inContext==OutputXRef,
4695 // ctx==OutputXRef,
4696 // yyextra->newXRefKind==yyextra->xrefKind,
4697 // yyextra->xrefKind!=XRef_Item,
4698 // yyextra->newXRefItemKey==yyextra->xrefItemKey);
4699 //printf("refKind=%d yyextra->newXRefKind=%d xrefAppendToPrev=%d yyextra->xrefAppendFlag=%d\n",
4700 // yyextra->xrefKind,yyextra->newXRefKind,xrefAppendToPrev,yyextra->xrefAppendFlag);
4701
4702 //printf("setOutput(yyscanner,yyextra->inContext=%d ctx=%d)\n",yyextra->inContext,ctx);
4703 if (yyextra->inContext==OutputXRef) // end of XRef section => add the item
4704 {
4705 // See if we can append this new xref item to the previous one.
4706 // We know this at the start of the next item of the same
4707 // type and need to remember this until the end of that item.
4708 switch(yyextra->xrefKind)
4709 {
4710 case XRef_Todo:
4711 addXRefItem(yyscanner,DString("todo"),
4714 xrefAppendToPrev
4715 );
4716 break;
4717 case XRef_Test:
4718 addXRefItem(yyscanner,DString("test"),
4721 xrefAppendToPrev
4722 );
4723 break;
4724 case XRef_Bug:
4725 addXRefItem(yyscanner,DString("bug"),
4728 xrefAppendToPrev
4729 );
4730 break;
4731 case XRef_Deprecated:
4732 addXRefItem(yyscanner,DString("deprecated"),
4735 xrefAppendToPrev || yyextra->current->spec.isDeprAttr()
4736 );
4737 break;
4738 case XRef_Item: // user defined list
4739 addXRefItem(yyscanner,yyextra->xrefItemKey,
4740 yyextra->xrefItemTitle,
4741 yyextra->xrefListTitle,
4742 xrefAppendToPrev
4743 );
4744 break;
4745 case XRef_None:
4746 ASSERT(0);
4747 break;
4748 }
4749 }
4750 yyextra->xrefItemKey = yyextra->newXRefItemKey;
4751
4752 int oldContext = yyextra->inContext;
4753 yyextra->inContext = ctx;
4754 if (yyextra->inContext!=OutputXRef && yyextra->inBody) yyextra->inContext=OutputInbody;
4755 switch(yyextra->inContext)
4756 {
4757 case OutputDoc:
4758 if (oldContext!=yyextra->inContext)
4759 {
4760 stripTrailingWhiteSpace(yyextra->current->doc);
4761 if (yyextra->current->doc.empty()) yyextra->current->docLine = yyextra->lineNr;
4762 if (yyextra->current->docFile.empty())
4763 {
4764 yyextra->current->docFile = yyextra->fileName;
4765 yyextra->current->docLine = yyextra->lineNr;
4766 }
4767 }
4768 yyextra->pOutputString = &yyextra->current->doc;
4769 break;
4770 case OutputBrief:
4771 {
4772 if (oldContext!=yyextra->inContext)
4773 {
4774 if (yyextra->current->brief.empty()) yyextra->current->briefLine = yyextra->lineNr;
4775 if (yyextra->current->briefFile.empty())
4776 {
4777 yyextra->current->briefFile = yyextra->fileName;
4778 yyextra->current->briefLine = yyextra->lineNr;
4779 }
4780 }
4781 bool foundMatch = false;
4782 if (yyextra->current->brief.stripWhiteSpace().empty()) // we only want one brief
4783 // description even if multiple
4784 // are given...
4785 {
4786 foundMatch = true;
4787 }
4788 else
4789 {
4790 std::string str = yyextra->current->brief.str();
4791 reg::Match match;
4792 if (reg::match(str,match,nonBrief_re)) // match found
4793 {
4794 size_t cnt = 0;
4795 for (size_t i = 0; i < match[2].str().size(); i++)
4796 {
4797 if (match[2].str()[i] == '\n') cnt++;
4798 }
4799 if (cnt>0)
4800 {
4801 yyextra->current->brief = yyextra->current->brief.left(yyextra->current->brief.length()-cnt);
4802 // set warning line correct
4803 yyextra->current->brief += " \\iline " + DString().setNum(cnt + static_cast<int>(std::stoul(match[1].str()))) + " \\ilinebr ";
4804 }
4805 foundMatch = true;
4806 }
4807 }
4808 if (foundMatch)
4809 {
4810 yyextra->pOutputString = &yyextra->current->brief;
4811 }
4812 else
4813 {
4814 if (!yyextra->current->doc.empty()) // when appending parts add a new line
4815 {
4816 yyextra->current->doc += "\n";
4817 }
4818 yyextra->pOutputString = &yyextra->current->doc;
4819 yyextra->inContext = OutputDoc; // need to switch to detailed docs, see bug 631380
4820 }
4821 }
4822 break;
4823 case OutputXRef:
4824 yyextra->pOutputString = &yyextra->outputXRef;
4825 // first item found, so can't append to previous
4826 //yyextra->xrefAppendFlag = false;
4827 break;
4828 case OutputInbody:
4829 yyextra->pOutputString = &yyextra->current->inbodyDocs;
4830 break;
4831 }
4832}
4833
4834
4835static void addAnchor(yyscan_t yyscanner,const DString &anchor, const DString &title)
4836{
4837 std::unique_lock<std::mutex> lock(g_sectionMutex);
4838 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4840 const SectionInfo *si = sm.find(anchor);
4841 if (si)
4842 {
4843 if (!si->ref().empty()) // we are from a tag file
4844 {
4845 si = sm.replace(anchor,yyextra->fileName,yyextra->lineNr,DString(),SectionType::Anchor,0);
4846 yyextra->current->anchors.push_back(si);
4847 }
4848 else if (si->lineNr() != -1)
4849 {
4850 warn(yyextra->fileName,yyextra->lineNr,
4851 "multiple use of section label '{}' while adding anchor, (first occurrence: {}, line {})",
4852 anchor,si->fileName(),si->lineNr());
4853 }
4854 else
4855 {
4856 warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '{}' while adding anchor, (first occurrence: {})",
4857 anchor,si->fileName());
4858 }
4859 }
4860 else
4861 {
4862 si = sm.add(anchor,yyextra->fileName,yyextra->lineNr,title,SectionType::Anchor,0);
4863 yyextra->current->anchors.push_back(si);
4864 }
4865}
4866
4867// add a string to the output
4868static inline void addOutput(yyscan_t yyscanner,const char *s)
4869{
4870 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4871 //printf("addOutput(yyscanner,%s)\n",s);
4872 *yyextra->pOutputString+=s;
4873}
4874
4875// add a string to the output
4876static inline void addOutput(yyscan_t yyscanner,const DString &s)
4877{
4878 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4879 //printf("addOutput(yyscanner,%s)\n",s);
4880 *yyextra->pOutputString+=s;
4881}
4882
4883// add a character to the output
4884static inline void addOutput(yyscan_t yyscanner,char c)
4885{
4886 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4887 *yyextra->pOutputString+=c;
4888}
4889
4890static void addIline(yyscan_t yyscanner,int lineNr)
4891{
4892 char cmd[30];
4893 snprintf(cmd,30," \\iline %d ",lineNr);
4894 addOutput(yyscanner, cmd);
4895}
4896
4897static void addIlineBreak(yyscan_t yyscanner,int lineNr)
4898{
4899 char cmd[30];
4900 snprintf(cmd,30," \\iline %d \\ilinebr ",lineNr);
4901 addOutput(yyscanner, cmd);
4902}
4903
4904static void endBrief(yyscan_t yyscanner)
4905{
4906 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4907 std::string_view str = yyextra->current->brief.view();
4908 reg::Match match;
4909 if (!stripWhiteSpace(str).empty() && !reg::match(str,match,nonBrief_re))
4910 { // only go to the detailed description if we have
4911 // found some brief description and not just whitespace
4912 yyextra->briefEndsAtDot=false;
4913 setOutput(yyscanner,OutputDoc);
4914 if (yyextra->current->doc.stripWhiteSpace().empty())
4915 {
4916 yyextra->current->docLine = yyextra->lineNr;
4917 yyextra->current->doc = "";
4918 }
4919 else
4920 {
4921 addIline(yyscanner,yyextra->lineNr);
4922 }
4923 addOutput(yyscanner,yytext);
4924 }
4925 else
4926 {
4927 int saveLineNr = yyextra->lineNr;
4928 lineCount(yyscanner);
4929 yyextra->current->briefLine = yyextra->lineNr;
4930 yyextra->lineNr = saveLineNr;
4931 }
4932}
4933
4934static int yyread(yyscan_t yyscanner,char *buf,int max_size)
4935{
4936 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4937 yyextra->prevPosition=yyextra->inputPosition;
4938 int c=0;
4939 while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
4940 {
4941 *buf = yyextra->inputString[yyextra->inputPosition++] ;
4942 //printf("%d (%c)\n",*buf,*buf);
4943 c++; buf++;
4944 }
4945 return c;
4946}
4947
4948//----------------------------------------------------------------------------
4949
4950static void checkFormula(yyscan_t yyscanner)
4951{
4952 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
4953 if (YY_START==ReadFormulaShort || YY_START==ReadFormulaShortSection ||
4954 YY_START==ReadFormulaRound || YY_START==ReadFormulaRoundSection ||
4955 YY_START==ReadFormulaLong)
4956 {
4957 warn(yyextra->fileName,yyextra->lineNr,"End of comment block while inside formula.");
4958 }
4959}
4960
4961//----------------------------------------------------------------------------
4962
4968
4970{
4971 commentscanYYlex_init_extra(&p->extra,&p->yyscanner);
4972#ifdef FLEX_DEBUG
4973 commentscanYYset_debug(Debug::isFlagSet(Debug::Lex_commentscan)?1:0,p->yyscanner);
4974#endif
4975}
4976
4978{
4979 commentscanYYlex_destroy(p->yyscanner);
4980}
4981
4983 /* in */ Entry *curEntry,
4984 /* in */ const DString &comment,
4985 /* in */ const DString &fileName,
4986 /* in,out */ int &lineNr,
4987 /* in */ bool isBrief,
4988 /* in */ bool isAutoBriefOn,
4989 /* in */ bool isInbody,
4990 /* in,out */ Protection &prot,
4991 /* in,out */ int &position,
4992 /* out */ bool &newEntryNeeded,
4993 /* in */ bool markdownSupport,
4994 /* inout */ GuardedSectionStack *guards
4995 )
4996{
4997 AUTO_TRACE("comment='{}' fileName={} lineNr={} isBrief={} isAutoBriefOn={} inInbody={}"
4998 " prot={} markdownSupport={}",Trace::trunc(comment),fileName,lineNr,isBrief,
4999 isAutoBriefOn,isInbody,prot,markdownSupport);
5000 yyscan_t yyscanner = p->yyscanner;
5001 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
5002
5003 initParser(yyscanner);
5004 yyextra->guards = guards;
5005 yyextra->langParser = parser;
5006 yyextra->current = curEntry;
5007 yyextra->current->docLine = (lineNr > 1 ? lineNr : 1);
5008 if (comment.empty()) return false; // avoid empty strings
5009 yyextra->inputString = comment;
5010 yyextra->inputString.append(" ");
5011 yyextra->inputPosition = position;
5012 yyextra->lineNr = lineNr;
5013 yyextra->fileName = fileName;
5014 yyextra->protection = prot;
5015 yyextra->needNewEntry = false;
5016 yyextra->xrefKind = XRef_None;
5017 yyextra->xrefAppendFlag = false;
5018 yyextra->insidePre = false;
5019 yyextra->parseMore = false;
5020 yyextra->inBody = isInbody;
5021 yyextra->markdownSupport= markdownSupport;
5022 yyextra->outputXRef.clear();
5023 if (!isBrief && !isAutoBriefOn && !yyextra->current->doc.empty())
5024 { // add newline separator between detailed comment blocks
5025 yyextra->current->doc += '\n';
5026 }
5027 setOutput(yyscanner, isBrief || isAutoBriefOn ? OutputBrief : OutputDoc );
5028 yyextra->briefEndsAtDot = isAutoBriefOn;
5029 yyextra->condCount = 0;
5030 yyextra->sectionLevel = 0;
5031 yyextra->spaceBeforeCmd.clear();
5032 yyextra->spaceBeforeIf.clear();
5033 yyextra->htmlContextStack.clear();
5034
5035 DebugLex debugLex(Debug::Lex_commentscan, __FILE__, !fileName.empty() ? qPrint(fileName): nullptr);
5036 if (!yyextra->current->inbodyDocs.empty() && isInbody) // separate in body fragments
5037 {
5038 char cmd[30];
5039 snprintf(cmd,30,"\n\n\\iline %d \\ilinebr ",lineNr);
5040 yyextra->current->inbodyDocs+=cmd;
5041 }
5042
5043 Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: {}:{}\n"
5044 "input=[\n{}]\n",fileName,lineNr,yyextra->inputString
5045 );
5046
5047 commentscanYYrestart( nullptr, yyscanner );
5048 BEGIN( Comment );
5049 commentscanYYlex(yyscanner);
5050 setOutput(yyscanner, OutputDoc );
5051
5052 if (YY_START==OverloadParam) // comment ended with \overload
5053 {
5055 }
5056
5057 if (yyextra->insideParBlock)
5058 {
5059 warn(yyextra->fileName,yyextra->lineNr,
5060 "Documentation block ended while inside a \\parblock. Missing \\endparblock");
5061 }
5062
5063 yyextra->current->doc=stripLeadingAndTrailingEmptyLines(yyextra->current->doc,yyextra->current->docLine);
5064 yyextra->current->brief=stripLeadingAndTrailingEmptyLines(yyextra->current->brief,yyextra->current->docLine);
5065
5066 if (yyextra->current->section.isFileDoc() && yyextra->current->doc.empty())
5067 {
5068 // to allow a comment block with just a @file command.
5069 yyextra->current->doc="\n\n";
5070 }
5071
5072 if (yyextra->current->section.isMemberGrp() &&
5073 yyextra->docGroup.empty()) // @name section but no group started yet
5074 {
5075 yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr,true);
5076 }
5077
5078 Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: {}:{}\noutput=[\n"
5079 "brief=[line={}\n{}]\ndocs=[line={}\n{}]\ninbody=[line={}\n{}]\n]\n===========\n",
5080 fileName,lineNr,
5081 yyextra->current->briefLine,yyextra->current->brief,
5082 yyextra->current->docLine,yyextra->current->doc,
5083 yyextra->current->inbodyLine,yyextra->current->inbodyDocs
5084 );
5085
5086 checkFormula(yyscanner);
5087 prot = yyextra->protection;
5088
5089 yyextra->docGroup.addDocs(curEntry);
5090
5091 newEntryNeeded = yyextra->needNewEntry;
5092
5093 // if we did not proceed during this call, it does not make
5094 // sense to continue, since we get stuck. See bug 567346 for situations
5095 // were this happens
5096 if (yyextra->parseMore && position==yyextra->inputPosition) yyextra->parseMore=false;
5097
5098 if (!yyextra->parseMore && !yyextra->guards->empty())
5099 {
5100 warn(yyextra->fileName,yyextra->lineNr,"Documentation block ended in the middle of a conditional section!");
5101 }
5102
5103 if (yyextra->parseMore) position=yyextra->inputPosition; else position=0;
5104
5105 lineNr = yyextra->lineNr;
5106 AUTO_TRACE_EXIT("position={} parseMore={} newEntryNeeded={}",
5107 position,yyextra->parseMore,newEntryNeeded);
5108
5109 return yyextra->parseMore;
5110}
5111
5112static void handleGuard(yyscan_t yyscanner,const DString &expr)
5113{
5114 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
5115 CondParser prs;
5116 bool sectionEnabled = false;
5117 if (!expr.empty())
5118 {
5119 sectionEnabled=prs.parse(yyextra->fileName,yyextra->lineNr,expr.stripWhiteSpace());
5120 }
5121 bool parentEnabled = yyextra->guards->top().parentVisible();
5122 if (parentEnabled)
5123 {
5124 if (
5125 (sectionEnabled && yyextra->guardType==Guard_If) ||
5126 (!sectionEnabled && yyextra->guardType==Guard_IfNot)
5127 ) // section is visible
5128 {
5129
5130 yyextra->guards->top().setEnabled(true);
5131 yyextra->guards->top().setEnabledFound();
5132 BEGIN( GuardParamEnd );
5133 }
5134 else if (yyextra->guardType==Guard_ElseIf)
5135 {
5136 if (yyextra->guards->top().isEnabledFound())
5137 {
5138 yyextra->guards->top().setEnabled(false);
5139 BEGIN( SkipGuardedSection );
5140 }
5141 else if (sectionEnabled)
5142 {
5143 yyextra->guards->top().setEnabled(true);
5144 yyextra->guards->top().setEnabledFound();
5145 BEGIN( GuardParamEnd );
5146 }
5147 else
5148 {
5149 yyextra->guards->top().setEnabled(false);
5150 BEGIN( SkipGuardedSection );
5151 }
5152 }
5153 else // section is invisible
5154 {
5155 BEGIN( SkipGuardedSection );
5156 }
5157 }
5158 else // invisible because of parent
5159 {
5160 BEGIN( SkipGuardedSection );
5161 }
5162}
5163
5165{
5166 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5167 yyextra->docGroup.initGroupInfo(entry);
5168}
5169
5170void CommentScanner::enterFile(const DString &fileName,int lineNr)
5171{
5172 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5173 yyextra->docGroup.enterFile(fileName,lineNr);
5174}
5175
5176void CommentScanner::leaveFile(const DString &fileName,int lineNr)
5177{
5178 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5179 yyextra->docGroup.leaveFile(fileName,lineNr);
5180}
5181
5182void CommentScanner::enterCompound(const DString &fileName,int lineNr,const DString &name)
5183{
5184 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5185 yyextra->docGroup.enterCompound(fileName,lineNr,name);
5186}
5187
5188void CommentScanner::leaveCompound(const DString &fileName,int lineNr,const DString &name)
5189{
5190 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5191 yyextra->docGroup.leaveCompound(fileName,lineNr,name);
5192}
5193
5194void CommentScanner::open(Entry *e,const DString &fileName,int lineNr,bool implicit)
5195{
5196 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5197 yyextra->docGroup.open(e,fileName,lineNr,implicit);
5198}
5199
5200void CommentScanner::close(Entry *e,const DString &fileName,int lineNr,bool foundInline,bool implicit)
5201{
5202 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
5203 yyextra->docGroup.close(e,fileName,lineNr,foundInline,implicit);
5204}
5205
5207{
5208 return (docCmdMap.find(cmdName.str()) != docCmdMap.end());
5209}
5210
5211void CommentScanner::addDeprecatedDocs(Entry *current,const DString &fileName,int line,OutlineParserInterface *parser)
5212{
5213 static reg::Ex deprecated_re(R"(deprecated\s*(\‍(\s*\"([^\"]*)\"\s*\))?)");
5214 reg::Match match;
5215 std::string attr = current->attributes.str();
5216 if (reg::search(attr,match,deprecated_re))
5217 {
5218 DString docs;
5219 if (match.size()==3) // deprecated attribute with documentation
5220 {
5221 Markdown markdown(fileName,line);
5222 DString rawDoc = match[2].str();
5223 DString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(rawDoc,line) : rawDoc;
5224 std::shared_ptr<Entry> docEntry = std::make_shared<Entry>();
5225 GuardedSectionStack guards;
5226 bool newEntryNeeded = false;
5227 Protection prot = Protection::Public;
5228 int position=0;
5229 parseCommentBlock(parser,
5230 docEntry.get(),
5231 processedDoc,
5232 fileName,
5233 line,
5234 false, // isBrief
5235 false, // isAutoBriefOn
5236 false, // isInbody
5237 prot,
5238 position,
5239 newEntryNeeded,
5240 Config_getBool(MARKDOWN_SUPPORT), // markdownSupport
5241 &guards);
5242 docs = docEntry->doc;
5243 //printf("rawDoc='%s' processedDoc='%s' docs='%s'\n",qPrint(rawDoc),qPrint(processedDoc),qPrint(docs));
5244 }
5245 else // deprecated attribute without documentation
5246 {
5247 current->spec.setDeprAttr(true);
5248 }
5249 if (!docs.empty() || !current->spec.isDeprDoc()) // attribute has docs
5250 // or no @deprecated command found in comment yet
5251 {
5252 // add new deprecated xref item to the documentation of this entry
5253 addXRefItemToEntry(current,
5254 docs,
5255 "deprecated",
5258 false, // append
5259 false, // inBody
5260 line);
5261 }
5262 }
5263 else
5264 {
5265 //printf("no match in attributes='%s'\n",qPrint(attr));
5266 }
5267}
5268
5269
5270#include "commentscan.l.h"
void insert(const DString &label)
Insert a citation identified by label into the database.
Definition cite.cpp:96
static CitationManager & instance()
Definition cite.cpp:86
void open(Entry *e, const DString &fileName, int line, bool implicit=false)
void enterFile(const DString &fileName, int lineNr)
void initGroupInfo(Entry *entry)
void leaveFile(const DString &fileName, int lineNr)
std::unique_ptr< Private > p
void close(Entry *e, const DString &fileName, int line, bool foundInline, bool implicit=false)
static bool isCommand(const DString &cmdName)
void leaveCompound(const DString &fileName, int line, const DString &name)
bool parseCommentBlock(OutlineParserInterface *parser, Entry *curEntry, const DString &comment, const DString &fileName, int &lineNr, bool isBrief, bool isJavadocStyle, bool isInbody, Protection &prot, int &position, bool &newEntryNeeded, bool markdownEnabled, GuardedSectionStack *guards)
Invokes the comment block parser with the request to parse a single comment block.
void addDeprecatedDocs(Entry *current, const DString &fileName, int line, OutlineParserInterface *parser)
void enterCompound(const DString &fileName, int line, const DString &name)
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition condparser.h:28
bool parse(const DString &fileName, int lineNr, const DString &expr)
parses and evaluates the given expression.
void resize(size_t newlen)
Definition dstring.h:214
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:675
DString & append(char c)
Definition dstring.h:478
size_t size() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:159
DString & sprintf(const char *format,...)
Definition dstring.cpp:29
bool startsWith(const char *s) const
Definition dstring.h:589
@ Lex_commentscan
Definition debug.h:55
@ CommentScan
Definition debug.h:32
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:133
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:77
int docLine
line number at which the documentation was found
Definition entry.h:203
@ GROUPDOC_WEAK
weakgroup
Definition entry.h:124
@ GROUPDOC_ADD
addtogroup
Definition entry.h:123
DString doc
documentation block (partly parsed)
Definition entry.h:202
std::vector< const SectionInfo * > anchors
list of anchors defined in this entry
Definition entry.h:224
DString attributes
member's attributes (e.g. [[nodiscard]])
Definition entry.h:195
RefItemVector sli
special lists (test/todo/bug/deprecated/..) this entry is in
Definition entry.h:228
DString inbodyDocs
documentation inside the body of a function
Definition entry.h:208
TypeSpecifier spec
class/member specifiers
Definition entry.h:183
int addFormula(const DString &formulaText, int width=-1, int height=-1)
Definition formula.cpp:690
static FormulaManager & instance()
Definition formula.cpp:53
T * add(const char *k, Args &&... args)
Definition linkedmap.h:90
const T * find(const std::string &key) const
Definition linkedmap.h:47
Helper class to process markdown formatted text.
Definition markdown.h:32
DString process(const DString &input, int &startNewlines, bool fromParseInput=false)
static MermaidManager & instance()
Definition mermaid.cpp:33
void setHasInlineDiagrams()
Definition mermaid.cpp:243
This struct represents an item in the list of references.
Definition reflist.h:32
int id() const
Definition reflist.h:52
DString text() const
Definition reflist.h:45
void setText(const DString &text)
Definition reflist.h:36
RefList * list() const
Definition reflist.h:53
void setAnchor(const DString &anchor)
Definition reflist.h:37
List of cross-referenced items.
Definition reflist.h:80
DString listName() const
Definition reflist.h:101
RefItem * add()
Definition reflist.cpp:30
static RefListManager & instance()
Definition reflist.h:121
class that provide information about a section.
Definition section.h:58
DString fileName() const
Definition section.h:74
int lineNr() const
Definition section.h:73
DString ref() const
Definition section.h:72
singleton class that owns the list of all sections
Definition section.h:135
SectionInfo * replace(const DString &label, const DString &fileName, int lineNr, const DString &title, SectionType type, int level, const DString &ref=DString())
Definition section.h:157
SectionInfo * add(const SectionInfo &si)
Definition section.h:139
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
static constexpr int Anchor
Definition section.h:40
static constexpr int Section
Definition section.h:33
static constexpr int MaxLevel
Definition section.h:39
constexpr SectionType()
Definition section.h:44
static constexpr int Subsection
Definition section.h:34
static constexpr int Subsubsection
Definition section.h:35
static constexpr int Requirement
Definition section.h:42
static constexpr int Paragraph
Definition section.h:36
static constexpr int Subsubparagraph
Definition section.h:38
static constexpr int Subparagraph
Definition section.h:37
virtual DString trTestList()=0
virtual DString trBugList()=0
virtual DString trBug()=0
virtual DString trTodoList()=0
virtual DString trDeprecatedList()=0
virtual DString trDeprecated()=0
virtual DString trTodo()=0
virtual DString trTest()=0
Class representing a regular expression.
Definition regex.h:39
Object representing the matching results.
Definition regex.h:154
static const reg::Ex nonBrief_re(R"( *[\\@]ifile \"[^\"]*\" [\\@]iline (\d+) [\\@]ilinebr ([ \n]*))")
static void addXRefItemToEntry(Entry *current, const DString &docs, const DString &listName, const DString &itemTitle, const DString &listTitle, bool append, bool inBody, int lineNr)
#define AUTO_TRACE(...)
Definition docnode.cpp:50
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:52
#define ASSERT(x)
Definition dstring.h:29
DString trunc(const DString &s, size_t numChars=15)
Definition trace.h:56
bool search(std::string_view str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
Definition regex.cpp:847
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:858
Definition dstring.h:902
bool literal_at(const char *data, const char(&str)[N])
returns true iff data points to a substring that matches string literal str
Definition stringutil.h:101
commentscanYY_state extra
DString stripLeadingAndTrailingEmptyLines(const DString &s, int &docLine)
Special version of DString::stripWhiteSpace() that only strips completely blank lines.
Definition util.cpp:4223