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