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