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