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