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