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