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