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