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