1 /*****************************************************************************
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
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.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
16 %option never-interactive
17 %option prefix="commentscanYY"
19 %option extra-type="struct commentscanYY_state *"
22 // forward declare yyscan_t to improve typesafety
23 #define YY_TYPEDEF_YY_SCANNER_T
25 typedef yyguts_t *yyscan_t;
46 #include "commentscan.h"
47 #include "condparser.h"
56 #include "parserintf.h"
62 #define USE_STATE2STRING 0
64 // forward declarations
65 static bool handleBrief(yyscan_t yyscanner,const QCString &, const StringVector &);
66 static bool handleFn(yyscan_t yyscanner,const QCString &, const StringVector &);
67 static bool handleDef(yyscan_t yyscanner,const QCString &, const StringVector &);
68 static bool handleOverload(yyscan_t yyscanner,const QCString &, const StringVector &);
69 static bool handleEnum(yyscan_t yyscanner,const QCString &, const StringVector &);
70 static bool handleDefGroup(yyscan_t yyscanner,const QCString &, const StringVector &);
71 static bool handleAddToGroup(yyscan_t yyscanner,const QCString &, const StringVector &);
72 static bool handleWeakGroup(yyscan_t yyscanner,const QCString &, const StringVector &);
73 static bool handleNamespace(yyscan_t yyscanner,const QCString &, const StringVector &);
74 static bool handlePackage(yyscan_t yyscanner,const QCString &, const StringVector &);
75 static bool handleConcept(yyscan_t yyscanner,const QCString &, const StringVector &);
76 static bool handleClass(yyscan_t yyscanner,const QCString &, const StringVector &);
77 static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const StringVector &);
78 static bool handleProtocol(yyscan_t yyscanner,const QCString &, const StringVector &);
79 static bool handleCategory(yyscan_t yyscanner,const QCString &, const StringVector &);
80 static bool handleUnion(yyscan_t yyscanner,const QCString &, const StringVector &);
81 static bool handleStruct(yyscan_t yyscanner,const QCString &, const StringVector &);
82 static bool handleInterface(yyscan_t yyscanner,const QCString &, const StringVector &);
83 static bool handleIdlException(yyscan_t yyscanner,const QCString &, const StringVector &);
84 static bool handlePage(yyscan_t yyscanner,const QCString &, const StringVector &);
85 static bool handleMainpage(yyscan_t yyscanner,const QCString &, const StringVector &);
86 static bool handleFile(yyscan_t yyscanner,const QCString &, const StringVector &);
87 static bool handleDir(yyscan_t yyscanner,const QCString &, const StringVector &);
88 static bool handleExample(yyscan_t yyscanner,const QCString &, const StringVector &);
89 static bool handleDetails(yyscan_t yyscanner,const QCString &, const StringVector &);
90 static bool handleNoop(yyscan_t yyscanner,const QCString &, const StringVector &);
91 static bool handleName(yyscan_t yyscanner,const QCString &, const StringVector &);
92 static bool handleTodo(yyscan_t yyscanner,const QCString &, const StringVector &);
93 static bool handleTest(yyscan_t yyscanner,const QCString &, const StringVector &);
94 static bool handleBug(yyscan_t yyscanner,const QCString &, const StringVector &);
95 static bool handleSubpage(yyscan_t yyscanner,const QCString &s, const StringVector &);
96 static bool handleDeprecated(yyscan_t yyscanner,const QCString &, const StringVector &);
97 static bool handleXRefItem(yyscan_t yyscanner,const QCString &, const StringVector &);
98 static bool handleRelated(yyscan_t yyscanner,const QCString &, const StringVector &);
99 static bool handleRelatedAlso(yyscan_t yyscanner,const QCString &, const StringVector &);
100 static bool handleMemberOf(yyscan_t yyscanner,const QCString &, const StringVector &);
101 static bool handleRefItem(yyscan_t yyscanner,const QCString &, const StringVector &);
102 static bool handleSection(yyscan_t yyscanner,const QCString &, const StringVector &);
103 static bool handleAnchor(yyscan_t yyscanner,const QCString &, const StringVector &);
104 static bool handleImage(yyscan_t yyscanner,const QCString &, const StringVector &);
105 static bool handleCite(yyscan_t yyscanner,const QCString &, const StringVector &);
106 static bool handleFormatBlock(yyscan_t yyscanner,const QCString &, const StringVector &);
107 static bool handleAddIndex(yyscan_t yyscanner,const QCString &, const StringVector &);
108 static bool handleIf(yyscan_t yyscanner,const QCString &, const StringVector &);
109 static bool handleIfNot(yyscan_t yyscanner,const QCString &, const StringVector &);
110 static bool handleElseIf(yyscan_t yyscanner,const QCString &, const StringVector &);
111 static bool handleElse(yyscan_t yyscanner,const QCString &, const StringVector &);
112 static bool handleEndIf(yyscan_t yyscanner,const QCString &, const StringVector &);
113 static bool handleIngroup(yyscan_t yyscanner,const QCString &, const StringVector &);
114 static bool handleNoSubGrouping(yyscan_t yyscanner,const QCString &, const StringVector &);
115 static bool handleShowInitializer(yyscan_t yyscanner,const QCString &, const StringVector &);
116 static bool handleHideInitializer(yyscan_t yyscanner,const QCString &, const StringVector &);
117 static bool handleCallgraph(yyscan_t yyscanner,const QCString &, const StringVector &);
118 static bool handleHideCallgraph(yyscan_t yyscanner,const QCString &, const StringVector &);
119 static bool handleCallergraph(yyscan_t yyscanner,const QCString &, const StringVector &);
120 static bool handleHideCallergraph(yyscan_t yyscanner,const QCString &, const StringVector &);
121 static bool handleReferencedByRelation(yyscan_t yyscanner,const QCString &, const StringVector &);
122 static bool handleHideReferencedByRelation(yyscan_t yyscanner,const QCString &, const StringVector &);
123 static bool handleReferencesRelation(yyscan_t yyscanner,const QCString &, const StringVector &);
124 static bool handleHideReferencesRelation(yyscan_t yyscanner,const QCString &, const StringVector &);
125 static bool handleInternal(yyscan_t yyscanner,const QCString &, const StringVector &);
126 static bool handleStatic(yyscan_t yyscanner,const QCString &, const StringVector &);
127 static bool handlePure(yyscan_t yyscanner,const QCString &, const StringVector &);
128 static bool handlePrivate(yyscan_t yyscanner,const QCString &, const StringVector &);
129 static bool handlePrivateSection(yyscan_t yyscanner,const QCString &, const StringVector &);
130 static bool handleProtected(yyscan_t yyscanner,const QCString &, const StringVector &);
131 static bool handleProtectedSection(yyscan_t yyscanner,const QCString &, const StringVector &);
132 static bool handlePublic(yyscan_t yyscanner,const QCString &s, const StringVector &);
133 static bool handlePublicSection(yyscan_t yyscanner,const QCString &s, const StringVector &);
134 static bool handleToc(yyscan_t yyscanner,const QCString &s, const StringVector &);
135 static bool handleInherit(yyscan_t yyscanner,const QCString &, const StringVector &);
136 static bool handleExtends(yyscan_t yyscanner,const QCString &, const StringVector &);
137 static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const StringVector &);
138 static bool handleCopyBrief(yyscan_t yyscanner,const QCString &, const StringVector &);
139 static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const StringVector &);
140 static bool handleParBlock(yyscan_t yyscanner,const QCString &, const StringVector &);
141 static bool handleEndParBlock(yyscan_t yyscanner,const QCString &, const StringVector &);
142 static bool handleParam(yyscan_t yyscanner,const QCString &, const StringVector &);
143 static bool handleRetval(yyscan_t yyscanner,const QCString &, const StringVector &);
146 static const char *stateToString(int state);
149 typedef bool (*DocCmdFunc)(yyscan_t yyscanner,const QCString &name, const StringVector &optList);
151 enum class CommandSpacing
153 Invisible, // command sets some property but does not appear in the output.
154 Inline, // command appears inline in the output which can be a brief description.
155 Block, // command starts a new paragraphs / ends a brief description.
156 XRef // command is a cross reference (todo, bug, test, xrefitem).
161 DocCmdMap(DocCmdFunc h,CommandSpacing s) : handler(h), spacing(s) {}
163 CommandSpacing spacing;
166 // map of command to handler function
167 static const std::map< std::string, DocCmdMap > docCmdMap =
169 // command name handler function command spacing
170 { "addindex", { &handleAddIndex, CommandSpacing::Invisible }},
171 { "addtogroup", { &handleAddToGroup, CommandSpacing::Invisible }},
172 { "anchor", { &handleAnchor, CommandSpacing::Invisible }},
173 { "arg", { 0, CommandSpacing::Block }},
174 { "attention", { 0, CommandSpacing::Block }},
175 { "author", { 0, CommandSpacing::Block }},
176 { "authors", { 0, CommandSpacing::Block }},
177 { "brief", { &handleBrief, CommandSpacing::Invisible }},
178 { "bug", { &handleBug, CommandSpacing::XRef }},
179 { "callergraph", { &handleCallergraph, CommandSpacing::Invisible }},
180 { "callgraph", { &handleCallgraph, CommandSpacing::Invisible }},
181 { "category", { &handleCategory, CommandSpacing::Invisible }},
182 { "cite", { &handleCite, CommandSpacing::Inline }},
183 { "class", { &handleClass, CommandSpacing::Invisible }},
184 { "code", { &handleFormatBlock, CommandSpacing::Block }},
185 { "concept", { &handleConcept, CommandSpacing::Invisible }},
186 { "copybrief", { &handleCopyBrief, CommandSpacing::Invisible }},
187 { "copydetails", { &handleCopyDetails, CommandSpacing::Block }},
188 { "copydoc", { &handleCopyDoc, CommandSpacing::Block }},
189 { "copyright", { 0, CommandSpacing::Block }},
190 { "date", { 0, CommandSpacing::Block }},
191 { "def", { &handleDef, CommandSpacing::Invisible }},
192 { "defgroup", { &handleDefGroup, CommandSpacing::Invisible }},
193 { "deprecated", { &handleDeprecated, CommandSpacing::XRef }},
194 { "details", { &handleDetails, CommandSpacing::Block }},
195 { "dir", { &handleDir, CommandSpacing::Invisible }},
196 { "docbookinclude", { 0, CommandSpacing::Inline }},
197 { "docbookonly", { &handleFormatBlock, CommandSpacing::Invisible }},
198 { "dot", { &handleFormatBlock, CommandSpacing::Block }},
199 { "dotfile", { 0, CommandSpacing::Block }},
200 { "else", { &handleElse, CommandSpacing::Inline }},
201 { "elseif", { &handleElseIf, CommandSpacing::Inline }},
202 { "endif", { &handleEndIf, CommandSpacing::Inline }},
203 { "endparblock", { &handleEndParBlock, CommandSpacing::Block }},
204 { "enum", { &handleEnum, CommandSpacing::Invisible }},
205 { "example", { &handleExample, CommandSpacing::Invisible }},
206 { "exception", { 0, CommandSpacing::Block }},
207 { "extends", { &handleExtends, CommandSpacing::Invisible }},
208 { "file", { &handleFile, CommandSpacing::Invisible }},
209 { "fn", { &handleFn, CommandSpacing::Invisible }},
210 { "headerfile", { &handleHeaderFile, CommandSpacing::Invisible }},
211 { "hidecallergraph", { &handleHideCallergraph, CommandSpacing::Invisible }},
212 { "hidecallgraph", { &handleHideCallgraph, CommandSpacing::Invisible }},
213 { "hideinitializer", { &handleHideInitializer, CommandSpacing::Invisible }},
214 { "hiderefby", { &handleHideReferencedByRelation, CommandSpacing::Invisible }},
215 { "hiderefs", { &handleHideReferencesRelation, CommandSpacing::Invisible }},
216 { "htmlinclude", { 0, CommandSpacing::Inline }},
217 { "htmlonly", { &handleFormatBlock, CommandSpacing::Invisible }},
218 { "idlexcept", { &handleIdlException, CommandSpacing::Invisible }},
219 { "if", { &handleIf, CommandSpacing::Inline }},
220 { "ifnot", { &handleIfNot, CommandSpacing::Inline }},
221 { "image", { &handleImage, CommandSpacing::Block }},
222 { "implements", { &handleExtends, CommandSpacing::Invisible }},
223 { "include", { 0, CommandSpacing::Block }},
224 { "includelineno", { 0, CommandSpacing::Block }},
225 { "ingroup", { &handleIngroup, CommandSpacing::Invisible }},
226 { "inherit", { &handleInherit, CommandSpacing::Invisible }},
227 { "interface", { &handleInterface, CommandSpacing::Invisible }},
228 { "internal", { &handleInternal, CommandSpacing::Block }},
229 { "invariant", { 0, CommandSpacing::Block }},
230 { "latexinclude", { 0, CommandSpacing::Inline }},
231 { "latexonly", { &handleFormatBlock, CommandSpacing::Invisible }},
232 { "li", { 0, CommandSpacing::Block }},
233 { "line", { 0, CommandSpacing::Invisible }},
234 { "mainpage", { &handleMainpage, CommandSpacing::Invisible }},
235 { "maninclude", { 0, CommandSpacing::Inline }},
236 { "manonly", { &handleFormatBlock, CommandSpacing::Invisible }},
237 { "memberof", { &handleMemberOf, CommandSpacing::Invisible }},
238 { "msc", { &handleFormatBlock, CommandSpacing::Block }},
239 { "name", { &handleName, CommandSpacing::Invisible }},
240 { "namespace", { &handleNamespace, CommandSpacing::Invisible }},
241 { "noop", { &handleNoop, CommandSpacing::Invisible }},
242 { "nosubgrouping", { &handleNoSubGrouping, CommandSpacing::Invisible }},
243 { "note", { 0, CommandSpacing::Block }},
244 { "overload", { &handleOverload, CommandSpacing::Invisible }},
245 { "package", { &handlePackage, CommandSpacing::Invisible }},
246 { "page", { &handlePage, CommandSpacing::Invisible }},
247 { "par", { 0, CommandSpacing::Block }},
248 { "paragraph", { &handleSection, CommandSpacing::Block }},
249 { "param", { &handleParam, CommandSpacing::Block }},
250 { "parblock", { &handleParBlock, CommandSpacing::Block }},
251 { "post", { 0, CommandSpacing::Block }},
252 { "pre", { 0, CommandSpacing::Block }},
253 { "private", { &handlePrivate, CommandSpacing::Invisible }},
254 { "privatesection", { &handlePrivateSection, CommandSpacing::Invisible }},
255 { "property", { &handleFn, CommandSpacing::Invisible }},
256 { "protected", { &handleProtected, CommandSpacing::Invisible }},
257 { "protectedsection",{ &handleProtectedSection, CommandSpacing::Invisible }},
258 { "protocol", { &handleProtocol, CommandSpacing::Invisible }},
259 { "public", { &handlePublic, CommandSpacing::Invisible }},
260 { "publicsection", { &handlePublicSection, CommandSpacing::Invisible }},
261 { "pure", { &handlePure, CommandSpacing::Invisible }},
262 { "refitem", { &handleRefItem, CommandSpacing::Inline }},
263 { "related", { &handleRelated, CommandSpacing::Invisible }},
264 { "relatedalso", { &handleRelatedAlso, CommandSpacing::Invisible }},
265 { "relates", { &handleRelated, CommandSpacing::Invisible }},
266 { "relatesalso", { &handleRelatedAlso, CommandSpacing::Invisible }},
267 { "remark", { 0, CommandSpacing::Block }},
268 { "remarks", { 0, CommandSpacing::Block }},
269 { "result", { 0, CommandSpacing::Block }},
270 { "return", { 0, CommandSpacing::Block }},
271 { "returns", { 0, CommandSpacing::Block }},
272 { "retval", { &handleRetval, CommandSpacing::Block }},
273 { "rtfinclude", { 0, CommandSpacing::Inline }},
274 { "rtfonly", { &handleFormatBlock, CommandSpacing::Invisible }},
275 { "sa", { 0, CommandSpacing::Block }},
276 { "section", { &handleSection, CommandSpacing::Block }},
277 { "see", { 0, CommandSpacing::Block }},
278 { "short", { &handleBrief, CommandSpacing::Invisible }},
279 { "showinitializer", { &handleShowInitializer, CommandSpacing::Invisible }},
280 { "showrefby", { &handleReferencedByRelation, CommandSpacing::Invisible }},
281 { "showrefs", { &handleReferencesRelation, CommandSpacing::Invisible }},
282 { "since", { 0, CommandSpacing::Block }},
283 { "snippet", { 0, CommandSpacing::Block }},
284 { "snippetlineno", { 0, CommandSpacing::Block }},
285 { "startuml", { &handleFormatBlock, CommandSpacing::Block }},
286 { "static", { &handleStatic, CommandSpacing::Invisible }},
287 { "struct", { &handleStruct, CommandSpacing::Invisible }},
288 { "subpage", { &handleSubpage, CommandSpacing::Inline }},
289 { "subsection", { &handleSection, CommandSpacing::Block }},
290 { "subsubsection", { &handleSection, CommandSpacing::Block }},
291 { "tableofcontents", { &handleToc, CommandSpacing::Invisible }},
292 { "test", { &handleTest, CommandSpacing::XRef }},
293 { "throw", { 0, CommandSpacing::Block }},
294 { "throws", { 0, CommandSpacing::Block }},
295 { "todo", { &handleTodo, CommandSpacing::XRef }},
296 { "tparam", { 0, CommandSpacing::Block }},
297 { "typedef", { &handleFn, CommandSpacing::Invisible }},
298 { "union", { &handleUnion, CommandSpacing::Invisible }},
299 { "until", { 0, CommandSpacing::Block }},
300 { "var", { &handleFn, CommandSpacing::Invisible }},
301 { "verbatim", { &handleFormatBlock, CommandSpacing::Block }},
302 { "verbinclude", { 0, CommandSpacing::Inline }},
303 { "version", { 0, CommandSpacing::Block }},
304 { "warning", { 0, CommandSpacing::Block }},
305 { "weakgroup", { &handleWeakGroup, CommandSpacing::Invisible }},
306 { "xmlinclude", { 0, CommandSpacing::Inline }},
307 { "xmlonly", { &handleFormatBlock, CommandSpacing::Invisible }},
308 { "xrefitem", { &handleXRefItem, CommandSpacing::XRef }}
311 #define YY_NO_INPUT 1
312 #define YY_NO_UNISTD_H 1
313 #define YY_NEVER_INTERACTIVE 1
344 GuardedSection(bool enabled,bool parentVisible)
345 : m_enabled(enabled),m_parentVisible(parentVisible) {}
346 bool isEnabled() const { return m_enabled; }
347 bool parentVisible() const { return m_parentVisible; }
351 bool m_parentVisible;
354 /* -----------------------------------------------------------------
359 struct commentscanYY_state
361 OutlineParserInterface *langParser = 0; // the language parser that is calling us
362 QCString inputString; // input string
363 QCString currentCmd; // the command used
364 int inputPosition = 0; // read pointer
365 QCString fileName; // file name that is read from
366 int lineNr = 0; // line number in the input
367 bool inBody = FALSE; // was the comment found inside the body of a function?
368 OutputContext inContext; // are we inside the brief, details or xref part
369 bool briefEndsAtDot = FALSE; // does the brief description stop at a dot?
370 QCString formulaText; // Running text of a formula
371 QCString formulaEnv; // environment name
372 int formulaNewLines = 0; // amount of new lines in the formula
373 QCString *pOutputString = 0; // pointer to string to which the output is appended.
374 QCString outputXRef; // temp argument of todo/test/../xrefitem commands
375 QCString blockName; // preformatted block name (e.g. verbatim, latexonly,...)
376 XRefKind xrefKind = XRef_Item; // kind of cross-reference command
377 XRefKind newXRefKind = XRef_Item; //
378 GuardType guardType = Guard_If; // kind of guards for conditional section
379 bool enabledSectionFound = FALSE;
380 QCString functionProto; // function prototype
381 std::stack<GuardedSection> guards; // tracks nested conditional sections (if,ifnot,..)
382 Entry *current = 0; // working entry
384 bool needNewEntry = FALSE;
386 QCString sectionLabel;
387 QCString sectionTitle;
388 int sectionLevel = 0;
389 QCString xrefItemKey;
390 QCString newXRefItemKey;
391 QCString xrefItemTitle;
392 QCString xrefListTitle;
393 Protection protection = Public;
395 bool xrefAppendFlag = FALSE;
396 bool inGroupParamFound = FALSE;
398 bool insidePre = FALSE;
399 bool parseMore = FALSE;
402 int commentCount = 0;
403 QCString spaceBeforeCmd;
404 QCString spaceBeforeIf;
410 bool insideParBlock = FALSE;
411 bool inInternalDocs = FALSE;
412 int prevPosition = 0;
414 bool markdownSupport = TRUE;
418 static std::mutex g_sectionMutex;
419 static std::mutex g_formulaMutex;
420 static std::mutex g_citeMutex;
422 //-----------------------------------------------------------------------------
424 static QCString stripQuotes(const char *s);
425 static bool getDocSectionName(int s);
426 static SectionType sectionLevelToType(int level);
427 static void stripTrailingWhiteSpace(QCString &s);
429 static void initParser(yyscan_t yyscanner);
430 static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s);
431 static void lineCount(yyscan_t yyscanner);
432 static void addXRefItem(yyscan_t yyscanner,
433 const QCString &listName,const QCString &itemTitle,
434 const QCString &listTitle,bool append);
435 static QCString addFormula(yyscan_t yyscanner);
436 static void checkFormula(yyscan_t yyscanner);
437 static void addSection(yyscan_t yyscanner);
438 static inline void setOutput(yyscan_t yyscanner,OutputContext ctx);
439 static void addAnchor(yyscan_t yyscanner,const QCString &anchor);
440 static inline void addOutput(yyscan_t yyscanner,const char *s);
441 static inline void addOutput(yyscan_t yyscanner,const QCString &s);
442 static inline void addOutput(yyscan_t yyscanner,char c);
443 static void endBrief(yyscan_t yyscanner,bool addToOutput=TRUE);
444 static void handleGuard(yyscan_t yyscanner,const QCString &expr);
445 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
446 static void addCite(yyscan_t yyscanner);
447 static void addIline(yyscan_t yyscanner,int lineNr);
449 #define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0)
451 //-----------------------------------------------------------------------------
454 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
458 /* start command character */
460 XREFCMD {CMD}("bug"|"deprecated"|"test"|"todo"|"xrefitem")
462 TABLE [tT][aA][bB][lL][eE]
469 PARA [pP][aA][rR][aA]
470 CODE [cC][oO][dD][eE]
471 CAPTION [cC][aA][pP][tT][iI][oO][nN]
472 CENTER [cC][eE][nN][tT][eE][rR]
474 DETAILEDHTML {CENTER}|{DIV}|{PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA}
475 DETAILEDHTMLOPT {CODE}
480 BS ^(({B}*"/""/")?)(({B}*"*"+)?){B}*
482 DOCNL "\n"|"\\ilinebr"
485 FILESCHAR [a-z_A-Z0-9\x80-\xFF\\:\\\/\-\+@&#]
486 FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+@&#]
487 FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"")
488 ID [$a-z_A-Z\x80-\xFF][$a-z_A-Z0-9\x80-\xFF]*
489 LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
490 CITESCHAR [a-z_A-Z0-9\x80-\xFF\-\?]
491 CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/\?]*
492 CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*|"\""{CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*"\""
493 SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
494 SCOPENAME "$"?(({ID}?{BN}*("::"|"."){BN}*)*)((~{BN}*)?{ID})
495 TMPLSPEC "<"{BN}*[^>]+{BN}*">"
496 MAILADDR [a-z_A-Z0-9.+\-]+"@"[a-z_A-Z0-9\-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
497 RCSTAG "$"{ID}":"[^\n$]+"$"
506 // end of section title with asterisk
508 // end of section title without asterisk
513 /* comment parsing states. */
541 %x SkipGuardedSection
563 /* What can happen in while parsing a comment block:
564 * commands (e.g. @page, or \page)
565 * escaped commands (e.g. @@page or \\page).
566 * formulas (e.g. \f$...\f$ \f[...\f] \f{...\f} \f(...\f) )
567 * directories (e.g. \doxygen\src\)
568 * autolist end. (e.g. a dot on an otherwise empty line)
570 * end of brief description due to blank line.
571 * end of brief description due to some command (@command, or <command>).
572 * words and whitespace and other characters (#,?!, etc).
573 * grouping commands (e.g. @{ and @})
574 * language switch (e.g. \~english or \~).
575 * mail address (e.g. doxygen@gmail.com).
576 * quoted text, such as "foo@bar"
577 * XML commands, <summary></summary><remarks></remarks>
580 <Comment>{CMD}{CMD}[a-z_A-Z]+{B}* { // escaped command
581 addOutput(yyscanner,yytext);
583 <Comment>{CMD}{CMD}"~"[a-z_A-Z]* { // escaped command
584 addOutput(yyscanner,yytext);
586 <Comment>{MAILADDR} { // mail address
587 addOutput(yyscanner,yytext);
589 <Comment>"\""[^"\n]*"\"" { // quoted text
590 addOutput(yyscanner,yytext);
592 <Comment>("\\"[a-z_A-Z]+)+"\\" { // directory (or chain of commands!)
593 addOutput(yyscanner,yytext);
595 <Comment>"<"{DETAILEDHTML}{ATTR}">" { // HTML command that ends a brief description
596 setOutput(yyscanner,OutputDoc);
597 // continue with the same input
600 <Comment>"<"{DETAILEDHTMLOPT}{ATTR}">" { // HTML command that ends a brief description
601 if (yyextra->current->lang==SrcLangExt_CSharp)
603 setOutput(yyscanner,OutputDoc);
605 // continue with the same input
608 <Comment>"<summary>" { // start of a .NET XML style brief description
609 setOutput(yyscanner,OutputBrief);
610 addOutput(yyscanner,yytext);
612 <Comment>"<remarks>" { // start of a .NET XML style detailed description
613 setOutput(yyscanner,OutputDoc);
614 addOutput(yyscanner,yytext);
616 <Comment>"</summary>" { // start of a .NET XML style detailed description
617 addOutput(yyscanner,yytext);
618 setOutput(yyscanner,OutputDoc);
620 <Comment>"</remarks>" { // end of a brief or detailed description
621 setOutput(yyscanner,OutputDoc);
622 addOutput(yyscanner,yytext);
624 <Comment>"<"{CAPTION}{ATTR}">" {
625 QCString tag(yytext);
626 int s=tag.find("id=");
627 if (s!=-1) // command has id attribute
630 if (c=='\'' || c=='"') // valid start
632 int e=tag.find(c,s+4);
633 if (e!=-1) // found matching end
635 QCString id=tag.mid(s+4,e-s-4); // extract id
636 addAnchor(yyscanner,id);
640 addOutput(yyscanner,yytext);
642 <Comment>"<"{PRE}{ATTR}">" {
643 yyextra->insidePre=TRUE;
644 addOutput(yyscanner,yytext);
646 <Comment>"</"{PRE}">" {
647 yyextra->insidePre=FALSE;
648 addOutput(yyscanner,yytext);
650 <Comment>{RCSTAG} { // RCS tag which end a brief description
651 setOutput(yyscanner,OutputDoc);
657 <Comment>"<!\[CDATA\[" {
660 <Comment>{B}*{CMD}"endinternal"{B}* {
661 addOutput(yyscanner," \\endinternal ");
662 if (!yyextra->inInternalDocs)
663 warn(yyextra->fileName,yyextra->lineNr,
664 "found \\endinternal without matching \\internal"
666 yyextra->inInternalDocs = FALSE;
668 <Comment>{B}*"\\ilinebr"{B}* { // preserve spacing around \\ilinebr
669 addOutput(yyscanner,yytext);
671 <Comment>{B}*{CMD}[a-z_A-Z]+"{"[a-zA-Z_,:0-9\. ]*"}"{B}* |
672 <Comment>{B}*{CMD}[a-z_A-Z]+{B}* { // potentially interesting command
673 // the {B}* in the front was added for bug620924
674 QCString fullMatch = QCString(yytext);
675 int idx = fullMatch.find('{');
676 /* handle `\f{` and `@f{` as special cases */
677 if ((idx > 1) && (yytext[idx-1] == 'f') && (yytext[idx-2] == '\\' || yytext[idx-2] =='@')) REJECT;
678 int idxEnd = fullMatch.find("}",idx+1);
680 StringVector optList;
681 if (idx == -1) // no options
683 cmdName = QCString(yytext).stripWhiteSpace().mid(1); // to remove {CMD}
685 else // options present
687 cmdName = fullMatch.left(idx).stripWhiteSpace().mid(1); // to remove {CMD}
688 QCString optStr = fullMatch.mid(idx+1,idxEnd-idx-1).stripWhiteSpace();
689 optList = split(optStr.str(),",");
691 auto it = docCmdMap.find(cmdName.str());
692 //printf("lookup command '%s' found=%d\n",qPrint(cmdName),it!=docCmdMap.end());
693 if (it!=docCmdMap.end()) // special action is required
696 while (yytext[i]==' ' || yytext[i]=='\t') i++;
697 yyextra->spaceBeforeCmd = QCString(yytext).left(i);
698 CommandSpacing spacing = it->second.spacing;
699 if ((spacing==CommandSpacing::Block || spacing==CommandSpacing::XRef) &&
700 !(yyextra->inContext==OutputXRef && cmdName=="parblock"))
702 yyextra->briefEndsAtDot=FALSE;
703 bool insideXRef = yyextra->inContext==OutputXRef && spacing==CommandSpacing::XRef;
704 // this command forces the end of brief description
705 setOutput(yyscanner,insideXRef ? OutputXRef : OutputDoc);
707 //if (i>0) addOutput(yyscanner,QCString(yytext).left(i)); // removed for bug 689341
708 if (it->second.handler && it->second.handler(yyscanner, cmdName, optList))
710 // implicit split of the comment block into two
711 // entries. Restart the next block at the start
713 yyextra->parseMore=TRUE;
715 // yuk, this is probably not very portable across lex implementations,
716 // but we need to know the position in the input buffer where this
718 // for flex 2.5.33+ we should use YY_CURRENT_BUFFER_LVALUE
719 #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33))
720 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);
722 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf);
726 else if (it->second.handler==0)
728 // command without handler, to be processed
729 // later by parsedoc.cpp
730 addOutput(yyscanner,yytext);
733 else // command not relevant
735 addOutput(yyscanner,yytext);
738 <Comment>{B}*({CMD}{CMD})"f"[$\[{] { // escaped formula command
739 addOutput(yyscanner,yytext);
741 <Comment>{B}*{CMD}"~"[a-z_A-Z-]* { // language switch command
742 QCString langId = QCString(yytext).stripWhiteSpace().mid(2);
743 if (!langId.isEmpty() &&
744 qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE).data(),langId.data())!=0)
745 { // enable language specific section
749 <Comment>{B}*{CMD}"f{"[^}\n]+"}"("{"?) { // start of a formula with custom environment
750 setOutput(yyscanner,OutputDoc);
751 yyextra->formulaText="\\begin";
752 yyextra->formulaEnv=QCString(yytext).stripWhiteSpace().mid(2);
753 if (yyextra->formulaEnv.at(yyextra->formulaEnv.length()-1)=='{')
755 // remove trailing open brace
756 yyextra->formulaEnv=yyextra->formulaEnv.left(yyextra->formulaEnv.length()-1);
758 yyextra->formulaText+=yyextra->formulaEnv;
759 yyextra->formulaNewLines=0;
760 BEGIN(ReadFormulaLong);
762 <Comment>{B}*{CMD}"f$" { // start of a inline formula
763 yyextra->formulaText="$";
764 yyextra->formulaNewLines=0;
765 BEGIN(ReadFormulaShort);
767 <Comment>{B}*{CMD}"f(" { // start of a inline formula
768 yyextra->formulaText="";
769 yyextra->formulaNewLines=0;
770 BEGIN(ReadFormulaRound);
772 <Comment>{B}*{CMD}"f[" { // start of a block formula
773 setOutput(yyscanner,OutputDoc);
774 yyextra->formulaText="\\[";
775 yyextra->formulaNewLines=0;
776 BEGIN(ReadFormulaLong);
778 <Comment>{B}*{CMD}"{" { // begin of a group
779 //yyextra->langParser->handleGroupStartCommand(yyextra->memberGroupHeader);
780 yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr);
782 <Comment>{B}*{CMD}"}" { // end of a group
783 //yyextra->langParser->handleGroupEndCommand();
784 yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,TRUE);
785 yyextra->docGroup.clearHeader();
786 yyextra->parseMore=TRUE;
787 yyextra->needNewEntry = TRUE;
788 #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33))
789 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + (int)strlen(yytext);
791 yyextra->inputPosition=yyextra->prevPosition + (int)(yy_bp - yy_current_buffer->yy_ch_buf) + (int)strlen(yytext);
795 <Comment>{B}*{CMD}[$@\\&~<>#%] { // escaped character
796 addOutput(yyscanner,yytext);
798 <Comment>[a-z_A-Z]+ { // normal word
799 addOutput(yyscanner,yytext);
801 <Comment>^{B}*"."{Bopt}/\n { // explicit end autolist: e.g " ."
802 addOutput(yyscanner,yytext);
804 <Comment>^{B}*[1-9][0-9]*"."{B}+ |
805 <Comment>^{B}*[*+]{B}+ { // start of autolist
806 if (!yyextra->markdownSupport)
812 if (yyextra->inContext!=OutputXRef)
814 yyextra->briefEndsAtDot=FALSE;
815 setOutput(yyscanner,OutputDoc);
817 addOutput(yyscanner,yytext);
820 <Comment>^{B}*"-"{B}+ { // start of autolist
821 if (yyextra->inContext!=OutputXRef)
823 yyextra->briefEndsAtDot=FALSE;
824 setOutput(yyscanner,OutputDoc);
826 addOutput(yyscanner,yytext);
828 <Comment>^{B}*([\-:|]{B}*)*("--"|"---")({B}*[\-:|])*{Bopt}/\n { // horizontal line (dashed)
829 addOutput(yyscanner,yytext);
831 <Comment>{CMD}"---" { // escaped mdash
832 addOutput(yyscanner,yytext);
834 <Comment>{CMD}"--" { // escaped mdash
835 addOutput(yyscanner,yytext);
837 <Comment>"---" { // mdash
838 addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "—");
840 <Comment>"--" { // ndash
841 addOutput(yyscanner,yyextra->insidePre || yyextra->markdownSupport ? yytext : "–");
843 <Comment>"-#"{B}+ { // numbered item
844 if (yyextra->inContext!=OutputXRef)
846 yyextra->briefEndsAtDot=FALSE;
847 setOutput(yyscanner,OutputDoc);
849 addOutput(yyscanner,yytext);
851 <Comment>("."+)[a-z_A-Z0-9\)] { // . at start or in the middle of a word, or ellipsis
852 addOutput(yyscanner,yytext);
854 <Comment>".\\"[ \t] { // . with escaped space.
855 addOutput(yyscanner,yytext[0]);
856 addOutput(yyscanner,yytext[2]);
858 <Comment>".," { // . with comma such as "e.g.,"
859 addOutput(yyscanner,yytext);
861 <Comment>"...\\"[ \t] { // ellipsis with escaped space.
862 addOutput(yyscanner,"... ");
864 <Comment>"..."/[^\.] { // ellipsis
865 addOutput(yyscanner,"...");
867 <Comment>".."[\.]?/[^ \t\n] { // internal ellipsis
868 addOutput(yyscanner,yytext);
870 <Comment>(\n|\\ilinebr)({B}*(\n|\\ilinebr))+ { // at least one blank line (or blank line command)
871 if (yyextra->inContext==OutputXRef)
873 // see bug 613024, we need to put the newlines after ending the XRef section.
874 if (!yyextra->insideParBlock) setOutput(yyscanner,OutputDoc);
876 for (i=0;i<(yy_size_t)yyleng;)
878 if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++;
879 else if (strcmp(yytext+i,"\\ilinebr")==0) addOutput(yyscanner,"\\ilinebr"),i+=8;
883 else if (yyextra->inContext!=OutputBrief)
886 for (i=0;i<(yy_size_t)yyleng;)
888 if (yytext[i]=='\n') addOutput(yyscanner,'\n'),i++;
889 else if (strcmp(yytext+i,"\\ilinebr")==0) addOutput(yyscanner,"\\ilinebr"),i+=8;
892 setOutput(yyscanner,OutputDoc);
894 else // yyextra->inContext==OutputBrief
895 { // only go to the detailed description if we have
896 // found some brief description and not just whitespace
897 endBrief(yyscanner,TRUE);
899 lineCount(yyscanner);
901 <Comment>"." { // potential end of a JavaDoc style comment
902 addOutput(yyscanner,*yytext);
903 if (yyextra->briefEndsAtDot)
905 setOutput(yyscanner,OutputDoc);
906 yyextra->briefEndsAtDot=FALSE;
909 <Comment>{DOCNL} { // newline
910 addOutput(yyscanner,yytext);
911 if (*yytext == '\n') yyextra->lineNr++;
913 <Comment>. { // catch-all for anything else
914 addOutput(yyscanner,*yytext);
918 /* -------------- Rules for handling HTML comments ----------- */
920 <HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); }
921 <HtmlComment>{DOCNL} {
924 addOutput(yyscanner,*yytext);
928 <HtmlComment>[^\\\n\-]+ { // ignore unimportant characters
930 <HtmlComment>. { // ignore every else
933 <CdataSection>"\]\]>" {
936 <CdataSection>{DOCNL} {
937 addOutput(yyscanner,'\n');
938 if (*yytext=='\n') yyextra->lineNr++;
940 <CdataSection>[<>&] { // the special XML characters for iwhich the CDATA section is especially used
941 addOutput(yyscanner,'\\');
942 addOutput(yyscanner,*yytext);
944 <CdataSection>[^\\\n\]<>&]+ {
945 addOutput(yyscanner,yytext);
948 addOutput(yyscanner,*yytext);
951 /* -------------- Rules for handling formulas ---------------- */
953 <ReadFormulaShort>{CMD}"f$" { // end of inline formula
954 yyextra->formulaText+="$";
955 addOutput(yyscanner," "+addFormula(yyscanner));
958 <ReadFormulaRound>{CMD}"f)" { // end of inline formula
959 addOutput(yyscanner," "+addFormula(yyscanner));
962 <ReadFormulaLong>{CMD}"f]" { // end of block formula
963 yyextra->formulaText+="\\]";
964 addOutput(yyscanner," "+addFormula(yyscanner));
967 <ReadFormulaLong>{CMD}"f}" { // end of custom env formula
968 yyextra->formulaText+="\\end";
969 yyextra->formulaText+=yyextra->formulaEnv;
970 addOutput(yyscanner," "+addFormula(yyscanner));
973 <ReadFormulaLong,ReadFormulaShort,ReadFormulaRound>[^\\@\n]+ { // any non-special character
974 yyextra->formulaText+=yytext;
976 <ReadFormulaLong,ReadFormulaShort,ReadFormulaRound>\n { // new line
977 yyextra->formulaNewLines++;
978 yyextra->formulaText+=*yytext;
981 <ReadFormulaLong,ReadFormulaShort,ReadFormulaRound>. { // any other character
982 yyextra->formulaText+=*yytext;
985 /* ------------ handle argument of enum command --------------- */
987 <EnumDocArg1>{SCOPEID} { // handle argument
988 yyextra->current->name = yytext;
991 <EnumDocArg1>{LC} { // line continuation
993 addOutput(yyscanner,'\n');
995 <EnumDocArg1>{DOCNL} { // missing argument
996 warn(yyextra->fileName,yyextra->lineNr,
997 "missing argument after \\enum."
999 unput_string(yytext,yyleng);
1000 //addOutput(yyscanner,'\n');
1001 //if (*yytext=='\n') yyextra->lineNr++;
1004 <EnumDocArg1>. { // ignore other stuff
1007 /* ------------ handle argument of namespace command --------------- */
1009 <NameSpaceDocArg1>{SCOPENAME} { // handle argument
1010 yyextra->current->name = substitute(QCString(yytext),QCString("."),QCString("::"));
1013 <NameSpaceDocArg1>{LC} { // line continuation
1015 addOutput(yyscanner,'\n');
1017 <NameSpaceDocArg1>{DOCNL} { // missing argument
1018 warn(yyextra->fileName,yyextra->lineNr,
1019 "missing argument after "
1022 unput_string(yytext,yyleng);
1023 //addOutput(yyscanner,'\n');
1024 //if (*yytext=='\n') yyextra->lineNr++;
1027 <NameSpaceDocArg1>. { // ignore other stuff
1030 /* ------------ handle argument of package command --------------- */
1032 <PackageDocArg1>{ID}("."{ID})* { // handle argument
1033 yyextra->current->name = yytext;
1036 <PackageDocArg1>{LC} { // line continuation
1038 addOutput(yyscanner,'\n');
1040 <PackageDocArg1>{DOCNL} { // missing argument
1041 warn(yyextra->fileName,yyextra->lineNr,
1042 "missing argument after "
1045 unput_string(yytext,yyleng);
1046 //addOutput(yyscanner,'\n');
1047 //if (*yytext=='\n') yyextra->lineNr++;
1050 <PackageDocArg1>. { // ignore other stuff
1053 /* ------------ handle argument of concept command --------------- */
1055 <ConceptDocArg1>{SCOPEID} { // handle argument
1056 yyextra->current->name = yytext;
1059 <ConceptDocArg1>{LC} { // line continuation
1061 addOutput(yyscanner,'\n');
1063 <ConceptDocArg1>{DOCNL} { // missing argument
1064 warn(yyextra->fileName,yyextra->lineNr,
1065 "missing argument after "
1068 unput_string(yytext,yyleng);
1071 <ConceptDocArg1>. { // ignore other stuff
1075 /* ------ handle argument of class/struct/union command --------------- */
1077 <ClassDocArg1>{SCOPENAME}{TMPLSPEC} {
1078 yyextra->current->name = substitute(removeRedundantWhiteSpace(QCString(yytext)),".","::");
1079 BEGIN( ClassDocArg2 );
1081 <ClassDocArg1>{SCOPENAME} { // first argument
1082 yyextra->current->name = substitute(QCString(yytext),".","::");
1083 if (yyextra->current->section==Entry::PROTOCOLDOC_SEC)
1085 yyextra->current->name+="-p";
1087 // prepend outer scope name
1088 BEGIN( ClassDocArg2 );
1090 <CategoryDocArg1>{SCOPENAME}{B}*"("[^\)]+")" {
1091 yyextra->current->name = substitute(QCString(yytext),".","::");
1092 BEGIN( ClassDocArg2 );
1094 <ClassDocArg1,CategoryDocArg1>{LC} { // line continuation
1096 addOutput(yyscanner,'\n');
1098 <ClassDocArg1,CategoryDocArg1>{DOCNL} {
1099 warn(yyextra->fileName,yyextra->lineNr,
1100 "missing argument after "
1101 "'\\%s'.",qPrint(yyextra->currentCmd)
1103 //addOutput(yyscanner,'\n');
1104 //if (*yytext=='\n') yyextra->lineNr++;
1105 unput_string(yytext,yyleng);
1108 <ClassDocArg1,CategoryDocArg1>. { // ignore other stuff
1111 <ClassDocArg2>{DOCNL} {
1112 //addOutput(yyscanner,'\n');
1113 //if (*yytext=='\n') yyextra->lineNr++;
1114 unput_string(yytext,yyleng);
1117 <ClassDocArg2>{FILE}|"<>" { // second argument; include file
1118 yyextra->current->includeFile = yytext;
1119 BEGIN( ClassDocArg3 );
1121 <ClassDocArg2>{LC} { // line continuation
1123 addOutput(yyscanner,'\n');
1125 <ClassDocArg2>. { // ignore other stuff
1128 <ClassDocArg3>[<"]?{FILE}?[">]? { // third argument; include file name
1129 yyextra->current->includeName = yytext;
1132 <ClassDocArg3>{LC} { // line continuation
1134 addOutput(yyscanner,'\n');
1136 <ClassDocArg3>{DOCNL} {
1137 //if (*yytext=='\n') yyextra->lineNr++;
1138 unput_string(yytext,yyleng);
1141 <ClassDocArg3>. { // ignore other stuff
1144 /* --------- handle arguments of {def,add,weak}group commands --------- */
1146 <GroupDocArg1>{LABELID}(".html"?) { // group name
1147 yyextra->current->name = yytext;
1148 //lastDefGroup.groupname = yytext;
1149 //lastDefGroup.pri = yyextra->current->groupingPri();
1150 // the .html stuff is for Qt compatibility
1151 if (yyextra->current->name.right(5)==".html")
1153 yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-5);
1155 yyextra->current->type.resize(0);
1156 BEGIN(GroupDocArg2);
1158 <GroupDocArg1>"\\"{B}*"\n" { // line continuation
1160 addOutput(yyscanner,'\n');
1162 <GroupDocArg1>{DOCNL} { // missing argument!
1163 warn(yyextra->fileName,yyextra->lineNr,
1164 "missing group name after %s",
1165 yyextra->current->groupDocCmd()
1167 //addOutput(yyscanner,'\n');
1168 //if (*yytext=='\n') yyextra->lineNr++;
1169 unput_string(yytext,yyleng);
1172 <GroupDocArg1>. { // ignore other stuff
1174 <GroupDocArg2>"\\"{B}*"\n" { // line continuation
1176 addOutput(yyscanner,'\n');
1178 <GroupDocArg2>[^\n\\]+ { // title (stored in type)
1179 yyextra->current->type += yytext;
1180 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
1182 <GroupDocArg2>{DOCNL} {
1183 if ( yyextra->current->groupDocType==Entry::GROUPDOC_NORMAL &&
1184 yyextra->current->type.isEmpty()
1185 ) // defgroup requires second argument
1187 warn(yyextra->fileName,yyextra->lineNr,
1188 "missing title after "
1189 "\\defgroup %s", qPrint(yyextra->current->name)
1192 unput_string(yytext,yyleng);
1193 //if (*yytext=='\n') yyextra->lineNr++;
1194 //addOutput(yyscanner,'\n');
1197 <GroupDocArg2>. { // title (stored in type)
1198 yyextra->current->type += yytext;
1199 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
1202 /* --------- handle arguments of page/mainpage command ------------------- */
1204 <PageDocArg1>{FILE} { // first argument; page name
1205 yyextra->current->name = stripQuotes(yytext);
1206 yyextra->current->args = "";
1207 BEGIN( PageDocArg2 );
1209 <PageDocArg1>{LC} { yyextra->lineNr++;
1210 addOutput(yyscanner,'\n');
1212 <PageDocArg1>{DOCNL} {
1213 warn(yyextra->fileName,yyextra->lineNr,
1214 "missing argument after "
1217 unput_string(yytext,yyleng);
1218 //if (*yytext=='\n') yyextra->lineNr++;
1219 //addOutput(yyscanner,'\n');
1222 <PageDocArg1>. { // ignore other stuff
1224 <PageDocArg2>{DOCNL} { // second argument; page title
1225 unput_string(yytext,yyleng);
1226 //if (*yytext=='\n') yyextra->lineNr++;
1227 //addOutput(yyscanner,'\n');
1230 <PageDocArg2>{CMD}[<>] {
1232 QCString tmp(yytext);
1233 tmp = substitute(substitute(tmp,"@<","<"),"@>",">");
1234 tmp = substitute(substitute(tmp,"\<","<"),"\>",">");
1235 yyextra->current->args += tmp;
1238 yyextra->current->args += yytext;
1240 /* --------- handle arguments of the param command ------------ */
1241 <ParamArg1>{ID}/{B}*"," {
1242 addOutput(yyscanner,yytext);
1245 addOutput(yyscanner," , ");
1247 <ParamArg1>{DOCNL} {
1248 if (*yytext=='\n') yyextra->lineNr++;
1249 addOutput(yyscanner," ");
1252 addOutput(yyscanner,yytext);
1260 /* --------- handle arguments of the file/dir/example command ------------ */
1262 <FileDocArg1>{DOCNL} { // no file name specified
1263 unput_string(yytext,yyleng);
1264 //if (*yytext=='\n') yyextra->lineNr++;
1265 //addOutput(yyscanner,'\n');
1268 <FileDocArg1>{FILE} { // first argument; name
1269 yyextra->current->name = stripQuotes(yytext);
1272 <FileDocArg1>{LC} { yyextra->lineNr++;
1273 addOutput(yyscanner,'\n');
1275 <FileDocArg1>. { // ignore other stuff
1278 /* --------- handle arguments of the xrefitem command ------------ */
1280 <XRefItemParam1>{LABELID} { // first argument
1281 yyextra->newXRefItemKey=yytext;
1282 setOutput(yyscanner,OutputXRef);
1283 BEGIN(XRefItemParam2);
1285 <XRefItemParam1>{LC} { // line continuation
1287 addOutput(yyscanner,'\n');
1289 <XRefItemParam1>{DOCNL} { // missing arguments
1290 warn(yyextra->fileName,yyextra->lineNr,
1291 "Missing first argument of \\xrefitem"
1293 if (*yytext=='\n') yyextra->lineNr++;
1294 addOutput(yyscanner,'\n');
1295 yyextra->inContext = OutputDoc;
1298 <XRefItemParam1>. { // ignore other stuff
1301 <XRefItemParam2>"\""[^\n\"]*"\"" { // second argument
1302 yyextra->xrefItemTitle = stripQuotes(yytext);
1303 BEGIN(XRefItemParam3);
1305 <XRefItemParam2>{LC} { // line continuation
1307 addOutput(yyscanner,'\n');
1309 <XRefItemParam2>{DOCNL} { // missing argument
1310 warn(yyextra->fileName,yyextra->lineNr,
1311 "Missing second argument of \\xrefitem"
1313 if (*yytext=='\n') yyextra->lineNr++;
1314 addOutput(yyscanner,'\n');
1315 yyextra->inContext = OutputDoc;
1318 <XRefItemParam2>. { // ignore other stuff
1321 <XRefItemParam3>"\""[^\n\"]*"\"" { // third argument
1322 yyextra->xrefListTitle = stripQuotes(yytext);
1323 yyextra->xrefKind = XRef_Item;
1326 <XRefItemParam2,XRefItemParam3>{LC} { // line continuation
1328 addOutput(yyscanner,'\n');
1330 <XRefItemParam3>{DOCNL} { // missing argument
1331 warn(yyextra->fileName,yyextra->lineNr,
1332 "Missing third argument of \\xrefitem"
1334 if (*yytext=='\n') yyextra->lineNr++;
1335 addOutput(yyscanner,'\n');
1336 yyextra->inContext = OutputDoc;
1339 <XRefItemParam3>. { // ignore other stuff
1343 /* ----- handle arguments of the relates(also)/memberof command ------- */
1345 <RelatesParam1>({ID}("::"|"."))*{ID} { // argument
1346 yyextra->current->relates = yytext;
1347 //if (yyextra->current->mGrpId!=DOX_NOGROUP)
1349 // memberGroupRelates = yytext;
1353 <RelatesParam1>{LC} { // line continuation
1355 addOutput(yyscanner,'\n');
1357 <RelatesParam1>{DOCNL} { // missing argument
1358 warn(yyextra->fileName,yyextra->lineNr,
1359 "Missing argument of '\\%s' command",qPrint(yyextra->currentCmd)
1361 unput_string(yytext,yyleng);
1362 //if (*yytext=='\n') yyextra->lineNr++;
1363 //addOutput(yyscanner,'\n');
1366 <RelatesParam1>. { // ignore other stuff
1370 /* ----- handle arguments of the relates(also)/addindex commands ----- */
1372 <LineParam>{DOCNL} { // end of argument
1373 //if (*yytext=='\n') yyextra->lineNr++;
1374 //addOutput(yyscanner,'\n');
1375 unput_string(yytext,yyleng);
1378 <LineParam>{LC} { // line continuation
1380 addOutput(yyscanner,'\n');
1382 <LineParam>. { // ignore other stuff
1383 addOutput(yyscanner,*yytext);
1386 /* ----- handle arguments of the section/subsection/.. commands ------- */
1388 <SectionLabel>{LABELID} { // first argument
1389 yyextra->sectionLabel=yytext;
1390 addOutput(yyscanner,yytext);
1391 yyextra->sectionTitle.resize(0);
1392 BEGIN(SectionTitle);
1394 <SectionLabel>{DOCNL} { // missing argument
1395 warn(yyextra->fileName,yyextra->lineNr,
1396 "\\section command has no label"
1398 if (*yytext=='\n') yyextra->lineNr++;
1399 addOutput(yyscanner,'\n');
1402 <SectionLabel>. { // invalid character for section label
1403 warn(yyextra->fileName,yyextra->lineNr,
1404 "Invalid or missing section label"
1408 <SectionTitle>{STAopt}/"\n" { // end of section title
1409 addSection(yyscanner);
1410 addOutput(yyscanner,yytext);
1413 <SectionTitle>{STopt}/"\\ilinebr" { // end of section title
1414 addSection(yyscanner);
1415 addOutput(yyscanner,yytext);
1418 <SectionTitle>{LC} { // line continuation
1420 addOutput(yyscanner,'\n');
1422 <SectionTitle>[^\n@\\]* { // any character without special meaning
1423 yyextra->sectionTitle+=yytext;
1424 addOutput(yyscanner,yytext);
1426 <SectionTitle>({CMD}{CMD}){ID} { // unescape escaped command
1427 yyextra->sectionTitle+=&yytext[1];
1428 addOutput(yyscanner,yytext);
1430 <SectionTitle>{CMD}[$@\\&~<>#%] { // unescape escaped character
1431 yyextra->sectionTitle+=yytext[1];
1432 addOutput(yyscanner,yytext);
1434 <SectionTitle>. { // anything else
1435 yyextra->sectionTitle+=yytext;
1436 addOutput(yyscanner,*yytext);
1439 /* ----- handle arguments of the subpage command ------- */
1441 <SubpageLabel>{LABELID} { // first argument
1442 addOutput(yyscanner,yytext);
1443 // we add subpage labels as a kind of "inheritance" relation to prevent
1444 // needing to add another list to the Entry class.
1445 yyextra->current->extends.push_back(BaseInfo(QCString(yytext),Public,Normal));
1446 BEGIN(SubpageTitle);
1448 <SubpageLabel>{DOCNL} { // missing argument
1449 warn(yyextra->fileName,yyextra->lineNr,
1450 "\\subpage command has no label"
1452 if (*yytext=='\n') yyextra->lineNr++;
1453 addOutput(yyscanner,'\n');
1456 <SubpageTitle>{DOCNL} { // no title, end command
1457 addOutput(yyscanner,yytext);
1460 <SubpageTitle>[ \t]*"\""[^\"\n]*"\"" { // add title, end of command
1461 addOutput(yyscanner,yytext);
1464 <SubpageTitle>. { // no title, end of command
1469 /* ----- handle arguments of the anchor command ------- */
1471 <AnchorLabel>{LABELID} { // found argument
1472 addAnchor(yyscanner,QCString(yytext));
1473 addOutput(yyscanner,yytext);
1476 <AnchorLabel>{DOCNL} { // missing argument
1477 warn(yyextra->fileName,yyextra->lineNr,
1478 "\\anchor command has no label"
1480 if (*yytext=='\n') yyextra->lineNr++;
1481 addOutput(yyscanner,'\n');
1484 <AnchorLabel>. { // invalid character for anchor label
1485 warn(yyextra->fileName,yyextra->lineNr,
1486 "Invalid or missing anchor label"
1492 /* ----- handle arguments of the preformatted block commands ------- */
1494 <FormatBlock>{CMD}("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endrtfonly"|"endmanonly"|"enddot"|"endcode"|"endmsc")/{NW} { // possible ends
1495 addOutput(yyscanner,yytext);
1496 if (&yytext[4]==yyextra->blockName) // found end of the block
1501 <FormatBlock>{CMD}"enduml" {
1502 addOutput(yyscanner,yytext);
1503 if (yyextra->blockName=="startuml") // found end of the block
1508 <FormatBlock>[^ \@\*\/\\\n]* { // some word
1509 addOutput(yyscanner,yytext);
1511 <FormatBlock>{DOCNL} { // new line
1512 if (*yytext=='\n') yyextra->lineNr++;
1513 addOutput(yyscanner,'\n');
1515 <FormatBlock>{CCS} { // start of a C-comment
1516 if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim")) yyextra->commentCount++;
1517 addOutput(yyscanner,yytext);
1519 <FormatBlock>{CCE} { // end of a C-comment
1520 addOutput(yyscanner,yytext);
1521 if (!(yyextra->blockName=="code" || yyextra->blockName=="verbatim"))
1523 yyextra->commentCount--;
1524 if (yyextra->commentCount<0)
1526 QCString endTag = "end"+yyextra->blockName;
1527 if (yyextra->blockName=="startuml") endTag="enduml";
1528 warn(yyextra->fileName,yyextra->lineNr,
1529 "found */ without matching /* while inside a \\%s block! Perhaps a missing \\%s?\n",qPrint(yyextra->blockName),qPrint(endTag));
1534 addOutput(yyscanner,*yytext);
1536 <FormatBlock><<EOF>> {
1537 QCString endTag = "end"+yyextra->blockName;
1538 if (yyextra->blockName=="startuml") endTag="enduml";
1539 warn(yyextra->fileName,yyextra->lineNr,
1540 "reached end of comment while inside a \\%s block; check for missing \\%s tag!",
1541 qPrint(yyextra->blockName),qPrint(endTag)
1546 /* ----- handle arguments of if/ifnot commands ------- */
1548 <GuardParam>{B}*"(" {
1549 yyextra->guardExpr=yytext;
1550 yyextra->roundCount=1;
1554 yyextra->guardExpr+=yytext;
1555 lineCount(yyscanner);
1558 yyextra->guardExpr+=yytext;
1559 yyextra->roundCount++;
1562 yyextra->guardExpr+=yytext;
1563 yyextra->roundCount--;
1564 if (yyextra->roundCount==0)
1566 handleGuard(yyscanner,yyextra->guardExpr);
1570 warn(yyextra->fileName,yyextra->lineNr,
1571 "invalid expression '%s' for yyextra->guards",qPrint(yyextra->guardExpr));
1575 <GuardParam>{B}*[a-z_A-Z0-9.\-]+ { // parameter of if/ifnot yyextra->guards
1576 handleGuard(yyscanner,QCString(yytext));
1578 <GuardParam>{DOCNL} { // end of argument
1579 if (*yytext=='\n') yyextra->lineNr++;
1580 //next line is commented out due to bug620924
1581 //addOutput(yyscanner,'\n');
1582 addIline(yyscanner,yyextra->lineNr);
1585 <GuardParam>{LC} { // line continuation
1587 addOutput(yyscanner,'\n');
1589 <GuardParam>. { // ignore other stuff
1590 addOutput(yyscanner,*yytext);
1592 <GuardParamEnd>{B}*{DOCNL} {
1593 lineCount(yyscanner);
1594 yyextra->spaceBeforeIf.resize(0);
1595 addIline(yyscanner,yyextra->lineNr);
1598 <GuardParamEnd>{B}* {
1599 if (!yyextra->spaceBeforeIf.isEmpty()) // needed for 665313 in combination with bug620924
1601 addOutput(yyscanner,yyextra->spaceBeforeIf);
1603 yyextra->spaceBeforeIf.resize(0);
1604 addIline(yyscanner,yyextra->lineNr);
1609 addIline(yyscanner,yyextra->lineNr);
1613 /* ----- handle skipping of conditional sections ------- */
1615 <SkipGuardedSection>{CMD}"ifnot"/{NW} {
1616 yyextra->guardType = Guard_IfNot;
1617 BEGIN( GuardParam );
1619 <SkipGuardedSection>{CMD}"if"/{NW} {
1620 yyextra->guardType = Guard_If;
1621 BEGIN( GuardParam );
1623 <SkipGuardedSection>{CMD}"endif"/{NW} {
1624 if (yyextra->guards.empty())
1626 warn(yyextra->fileName,yyextra->lineNr,
1627 "found \\endif without matching start command");
1631 GuardedSection s = yyextra->guards.top();
1632 yyextra->guards.pop();
1633 bool parentVisible = s.parentVisible();
1636 yyextra->enabledSectionFound=TRUE;
1637 BEGIN( GuardParamEnd );
1641 <SkipGuardedSection>{CMD}"else"/{NW} {
1642 if (yyextra->guards.empty())
1644 warn(yyextra->fileName,yyextra->lineNr,
1645 "found \\else without matching start command");
1649 if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible())
1651 yyextra->guards.pop();
1652 yyextra->guards.push(GuardedSection(TRUE,TRUE));
1653 yyextra->enabledSectionFound=TRUE;
1654 BEGIN( GuardParamEnd );
1658 <SkipGuardedSection>{CMD}"elseif"/{NW} {
1659 if (yyextra->guards.empty())
1661 warn(yyextra->fileName,yyextra->lineNr,
1662 "found \\elseif without matching start command");
1666 if (!yyextra->enabledSectionFound && yyextra->guards.top().parentVisible())
1668 yyextra->guardType=Guard_If;
1669 yyextra->guards.pop();
1670 BEGIN( GuardParam );
1674 <SkipGuardedSection>{DOCNL} { // skip line
1675 if (*yytext=='\n') yyextra->lineNr++;
1676 //addOutput(yyscanner,'\n');
1678 <SkipGuardedSection>[^ \\@\n]+ { // skip non-special characters
1680 <SkipGuardedSection>. { // any other character
1684 /* ----- handle skipping of internal section ------- */
1686 <SkipInternal>{DOCNL} { // skip line
1687 if (*yytext=='\n') yyextra->lineNr++;
1688 addOutput(yyscanner,'\n');
1690 <SkipInternal>[@\\]"if"/[ \t] {
1691 yyextra->condCount++;
1693 <SkipInternal>[@\\]"ifnot"/[ \t] {
1694 yyextra->condCount++;
1696 <SkipInternal>[@\\]/"endif" {
1697 yyextra->condCount--;
1698 if (yyextra->condCount<0) // handle conditional section around of \internal, see bug607743
1704 <SkipInternal>[@\\]/"section"[ \t] {
1705 if (yyextra->sectionLevel>0)
1711 <SkipInternal>[@\\]/"subsection"[ \t] {
1712 if (yyextra->sectionLevel>1)
1718 <SkipInternal>[@\\]/"subsubsection"[ \t] {
1719 if (yyextra->sectionLevel>2)
1725 <SkipInternal>[@\\]/"paragraph"[ \t] {
1726 if (yyextra->sectionLevel>3)
1732 <SkipInternal>[@\\]"endinternal"[ \t]* {
1735 <SkipInternal>[^ \\@\n]+ { // skip non-special characters
1737 <SkipInternal>. { // any other character
1741 /* ----- handle argument of name command ------- */
1743 <NameParam>{DOCNL} { // end of argument
1744 //if (*yytext=='\n') yyextra->lineNr++;
1745 //addOutput(yyscanner,'\n');
1746 unput_string(yytext,yyleng);
1749 <NameParam>{LC} { // line continuation
1751 addOutput(yyscanner,'\n');
1752 yyextra->docGroup.appendHeader(' ');
1754 <NameParam>. { // ignore other stuff
1755 yyextra->docGroup.appendHeader(*yytext);
1756 yyextra->current->name+=*yytext;
1759 /* ----- handle argument of noop command ------- */
1760 <Noop>{DOCNL} { // end of argument
1761 if (*yytext=='\n') yyextra->lineNr++;
1762 addOutput(yyscanner,'\n');
1765 <Noop>. { // ignore other stuff
1767 /* ----- handle argument of ingroup command ------- */
1769 <InGroupParam>{LABELID} { // group id
1770 yyextra->current->groups.push_back(
1771 Grouping(QCString(yytext), Grouping::GROUPING_INGROUP)
1773 yyextra->inGroupParamFound=TRUE;
1775 <InGroupParam>{DOCNL} { // missing argument
1776 if (!yyextra->inGroupParamFound)
1778 warn(yyextra->fileName,yyextra->lineNr,
1779 "Missing group name for \\ingroup command"
1782 //if (*yytext=='\n') yyextra->lineNr++;
1783 //addOutput(yyscanner,'\n');
1784 unput_string(yytext,yyleng);
1787 <InGroupParam>{LC} { // line continuation
1789 addOutput(yyscanner,'\n');
1791 <InGroupParam>. { // ignore other stuff
1792 addOutput(yyscanner,*yytext);
1795 /* ----- handle argument of fn command ------- */
1797 <FnParam>{DOCNL} { // end of argument
1798 if (yyextra->braceCount==0)
1800 //if (*yytext=='\n') yyextra->lineNr++;
1801 //addOutput(yyscanner,'\n');
1802 unput_string(yytext,yyleng);
1803 yyextra->langParser->parsePrototype(yyextra->functionProto);
1807 <FnParam>{LC} { // line continuation
1809 yyextra->functionProto+=' ';
1811 <FnParam>[^@\\\n()]+ { // non-special characters
1812 yyextra->functionProto+=yytext;
1815 yyextra->functionProto+=yytext;
1816 yyextra->braceCount++;
1819 yyextra->functionProto+=yytext;
1820 yyextra->braceCount--;
1822 <FnParam>. { // add other stuff
1823 yyextra->functionProto+=*yytext;
1827 /* ----- handle argument of overload command ------- */
1830 <OverloadParam>{DOCNL} { // end of argument
1831 if (*yytext=='\n') yyextra->lineNr++;
1832 if (yyextra->functionProto.stripWhiteSpace().isEmpty())
1833 { // plain overload command
1834 addOutput(yyscanner,getOverloadDocs());
1835 addOutput(yyscanner,'\n');
1837 else // overload declaration
1839 makeStructuralIndicator(yyscanner,Entry::OVERLOADDOC_SEC);
1840 yyextra->langParser->parsePrototype(yyextra->functionProto);
1844 <OverloadParam>{LC} { // line continuation
1846 yyextra->functionProto+=' ';
1848 <OverloadParam>. { // add other stuff
1849 yyextra->functionProto+=*yytext;
1852 /* ----- handle argument of inherit command ------- */
1854 <InheritParam>({ID}("::"|"."))*{ID} { // found argument
1855 yyextra->current->extends.push_back(
1856 BaseInfo(removeRedundantWhiteSpace(QCString(yytext)),Public,Normal)
1860 <InheritParam>{DOCNL} { // missing argument
1861 warn(yyextra->fileName,yyextra->lineNr,
1862 "\\inherit command has no argument"
1864 if (*yytext=='\n') yyextra->lineNr++;
1865 addOutput(yyscanner,'\n');
1868 <InheritParam>. { // invalid character for anchor label
1869 warn(yyextra->fileName,yyextra->lineNr,
1870 "Invalid or missing name for \\inherit command"
1875 /* ----- handle argument of extends and implements commands ------- */
1877 <ExtendsParam>({ID}("::"|"."))*{ID} { // found argument
1878 yyextra->current->extends.push_back(
1879 BaseInfo(removeRedundantWhiteSpace(QCString(yytext)),Public,Normal)
1883 <ExtendsParam>{DOCNL} { // missing argument
1884 warn(yyextra->fileName,yyextra->lineNr,
1885 "'\\%s' command has no argument",qPrint(yyextra->currentCmd)
1887 //if (*yytext=='\n') yyextra->lineNr++;
1888 //addOutput(yyscanner,'\n');
1889 unput_string(yytext,yyleng);
1892 <ExtendsParam>. { // ignore other stuff
1895 /* ----- handle language specific sections ------- */
1897 <SkipLang>[\\@]"~"[a-zA-Z-]* { /* language switch */
1898 QCString langId(&yytext[2]);
1899 if (langId.isEmpty() ||
1900 qstricmp(Config_getEnumAsString(OUTPUT_LANGUAGE).data(),langId.data())==0)
1901 { // enable language specific section
1905 <SkipLang>[^*@\\\n]* { /* any character not a *, @, backslash or new line */
1907 <SkipLang>{DOCNL} { /* new line in verbatim block */
1908 if (*yytext=='\n') yyextra->lineNr++;
1910 <SkipLang>. { /* any other character */
1913 /* ----- handle arguments of the cite command ------- */
1915 <CiteLabel>{CITEID} { // found argument
1917 addOutput(yyscanner,yytext);
1920 <CiteLabel>{DOCNL} { // missing argument
1921 warn(yyextra->fileName,yyextra->lineNr,
1922 "\\cite command has no label"
1924 //if (*yytext=='\n') yyextra->lineNr++;
1925 //addOutput(yyscanner,'\n');
1926 unput_string(yytext,yyleng);
1929 <CiteLabel>. { // invalid character for cite label
1930 warn(yyextra->fileName,yyextra->lineNr,
1931 "Invalid or missing cite label"
1936 /* ----- handle argument of the copydoc command ------- */
1940 if (*yytext=='\n') yyextra->lineNr++;
1941 addOutput(yyscanner,'\n');
1942 setOutput(yyscanner,OutputDoc);
1943 addOutput(yyscanner," \\copydetails ");
1944 addOutput(yyscanner,yyextra->copyDocArg);
1945 addOutput(yyscanner,"\n");
1949 yyextra->copyDocArg+=yytext;
1950 addOutput(yyscanner,yytext);
1953 yyextra->copyDocArg+=yytext;
1954 addOutput(yyscanner,yytext);
1958 <*>. { fprintf(stderr,"Lex scanner %s %sdefault rule for state %s: #%s#\n", __FILE__,yyextra->fileName ? ("(" + yyextra->fileName +") ").data(): "",stateToString(YY_START),yytext);}
1959 <*>\n { fprintf(stderr,"Lex scanner %s %sdefault rule newline for state %s.\n", __FILE__, yyextra->fileName ? ("(" + yyextra->fileName +") ").data(): "",stateToString(YY_START));}
1964 //----------------------------------------------------------------------------
1966 static bool handleBrief(yyscan_t yyscanner,const QCString &, const StringVector &)
1968 //printf("handleBrief\n");
1969 setOutput(yyscanner,OutputBrief);
1973 static bool handleFn(yyscan_t yyscanner,const QCString &, const StringVector &)
1975 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1976 bool stop=makeStructuralIndicator(yyscanner,Entry::MEMBERDOC_SEC);
1977 yyextra->functionProto.resize(0);
1978 yyextra->braceCount=0;
1983 static bool handleDef(yyscan_t yyscanner,const QCString &, const StringVector &)
1985 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1986 bool stop=makeStructuralIndicator(yyscanner,Entry::DEFINEDOC_SEC);
1987 yyextra->functionProto.resize(0);
1992 static bool handleOverload(yyscan_t yyscanner,const QCString &, const StringVector &)
1994 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1995 yyextra->functionProto.resize(0);
1996 BEGIN(OverloadParam);
2000 static bool handleEnum(yyscan_t yyscanner,const QCString &, const StringVector &)
2002 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2003 bool stop=makeStructuralIndicator(yyscanner,Entry::ENUMDOC_SEC);
2008 static bool handleDefGroup(yyscan_t yyscanner,const QCString &, const StringVector &)
2010 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2011 bool stop=makeStructuralIndicator(yyscanner,Entry::GROUPDOC_SEC);
2012 yyextra->current->groupDocType = Entry::GROUPDOC_NORMAL;
2013 BEGIN( GroupDocArg1 );
2017 static bool handleAddToGroup(yyscan_t yyscanner,const QCString &, const StringVector &)
2019 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2020 bool stop=makeStructuralIndicator(yyscanner,Entry::GROUPDOC_SEC);
2021 yyextra->current->groupDocType = Entry::GROUPDOC_ADD;
2022 BEGIN( GroupDocArg1 );
2026 static bool handleWeakGroup(yyscan_t yyscanner,const QCString &, const StringVector &)
2028 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2029 bool stop=makeStructuralIndicator(yyscanner,Entry::GROUPDOC_SEC);
2030 yyextra->current->groupDocType = Entry::GROUPDOC_WEAK;
2031 BEGIN( GroupDocArg1 );
2035 static bool handleNamespace(yyscan_t yyscanner,const QCString &, const StringVector &)
2037 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2038 bool stop=makeStructuralIndicator(yyscanner,Entry::NAMESPACEDOC_SEC);
2039 BEGIN( NameSpaceDocArg1 );
2043 static bool handlePackage(yyscan_t yyscanner,const QCString &, const StringVector &)
2045 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2046 bool stop=makeStructuralIndicator(yyscanner,Entry::PACKAGEDOC_SEC);
2047 BEGIN( PackageDocArg1 );
2051 static bool handleClass(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2053 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2054 bool stop=makeStructuralIndicator(yyscanner,Entry::CLASSDOC_SEC);
2055 yyextra->currentCmd = cmd;
2056 BEGIN( ClassDocArg1 );
2060 static bool handleConcept(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2062 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2063 bool stop=makeStructuralIndicator(yyscanner,Entry::CONCEPTDOC_SEC);
2064 yyextra->currentCmd = cmd;
2065 BEGIN( ConceptDocArg1 );
2069 static bool handleHeaderFile(yyscan_t yyscanner,const QCString &, const StringVector &)
2071 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2072 BEGIN( ClassDocArg2 );
2076 static bool handleProtocol(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2078 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2079 bool stop=makeStructuralIndicator(yyscanner,Entry::PROTOCOLDOC_SEC);
2080 yyextra->currentCmd = cmd;
2081 BEGIN( ClassDocArg1 );
2085 static bool handleCategory(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2087 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2088 bool stop=makeStructuralIndicator(yyscanner,Entry::CATEGORYDOC_SEC);
2089 yyextra->currentCmd = cmd;
2090 BEGIN( CategoryDocArg1 );
2094 static bool handleUnion(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2096 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2097 bool stop=makeStructuralIndicator(yyscanner,Entry::UNIONDOC_SEC);
2098 yyextra->currentCmd = cmd;
2099 BEGIN( ClassDocArg1 );
2103 static bool handleStruct(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2105 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2106 bool stop=makeStructuralIndicator(yyscanner,Entry::STRUCTDOC_SEC);
2107 yyextra->currentCmd = cmd;
2108 BEGIN( ClassDocArg1 );
2112 static bool handleInterface(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2114 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2115 bool stop=makeStructuralIndicator(yyscanner,Entry::INTERFACEDOC_SEC);
2116 yyextra->currentCmd = cmd;
2117 BEGIN( ClassDocArg1 );
2121 static bool handleIdlException(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2123 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2124 bool stop=makeStructuralIndicator(yyscanner,Entry::EXCEPTIONDOC_SEC);
2125 yyextra->currentCmd = cmd;
2126 BEGIN( ClassDocArg1 );
2130 static bool handlePage(yyscan_t yyscanner,const QCString &, const StringVector &)
2132 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2133 bool stop=makeStructuralIndicator(yyscanner,Entry::PAGEDOC_SEC);
2134 BEGIN( PageDocArg1 );
2138 static bool handleMainpage(yyscan_t yyscanner,const QCString &, const StringVector &)
2140 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2141 bool stop=makeStructuralIndicator(yyscanner,Entry::MAINPAGEDOC_SEC);
2144 yyextra->current->name = "mainpage";
2146 BEGIN( PageDocArg2 );
2150 static bool handleFile(yyscan_t yyscanner,const QCString &, const StringVector &)
2152 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2153 bool stop=makeStructuralIndicator(yyscanner,Entry::FILEDOC_SEC);
2156 yyextra->current->name = yyextra->fileName;
2158 BEGIN( FileDocArg1 );
2162 static bool handleParam(yyscan_t yyscanner,const QCString &, const StringVector &)
2164 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2165 // we need process param and retval arguments to escape leading underscores in case of
2166 // markdown processing, see bug775493
2167 addOutput(yyscanner,"@param ");
2172 static bool handleRetval(yyscan_t yyscanner,const QCString &, const StringVector &)
2174 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2175 addOutput(yyscanner,"@retval ");
2180 static bool handleDir(yyscan_t yyscanner,const QCString &, const StringVector &)
2182 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2183 bool stop=makeStructuralIndicator(yyscanner,Entry::DIRDOC_SEC);
2184 if (!stop) yyextra->current->name = yyextra->fileName;
2185 BEGIN( FileDocArg1 );
2189 static bool handleExample(yyscan_t yyscanner,const QCString &cmd, const StringVector &optList)
2191 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2192 Entry::Sections section=Entry::EXAMPLE_SEC;
2193 for (const auto &opt : optList)
2197 section=Entry::EXAMPLE_LINENO_SEC;
2201 warn(yyextra->fileName,yyextra->lineNr,
2202 "unsupported option '%s' for command '\\%s'",opt.c_str(),qPrint(cmd));
2205 bool stop=makeStructuralIndicator(yyscanner,section);
2206 if (!stop) yyextra->current->name = yyextra->fileName;
2207 BEGIN( FileDocArg1 );
2211 static bool handleDetails(yyscan_t yyscanner,const QCString &, const StringVector &)
2213 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2214 if (yyextra->inContext!=OutputBrief)
2216 addOutput(yyscanner,"\\ilinebr\\ilinebr "); // treat @details outside brief description
2217 // as a new paragraph
2219 setOutput(yyscanner,OutputDoc);
2223 static bool handleNoop(yyscan_t yyscanner,const QCString &, const StringVector &)
2225 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2230 static bool handleName(yyscan_t yyscanner,const QCString &, const StringVector &)
2232 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2233 bool stop=makeStructuralIndicator(yyscanner,Entry::MEMBERGRP_SEC);
2236 yyextra->docGroup.clearHeader();
2238 if (!yyextra->docGroup.isEmpty()) // end of previous member group
2240 yyextra->docGroup.close(yyextra->current,yyextra->fileName,yyextra->lineNr,TRUE,true);
2246 static bool handleTodo(yyscan_t yyscanner,const QCString &, const StringVector &)
2248 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2249 yyextra->newXRefKind = XRef_Todo;
2250 setOutput(yyscanner,OutputXRef);
2251 yyextra->xrefKind = XRef_Todo;
2255 static bool handleTest(yyscan_t yyscanner,const QCString &, const StringVector &)
2257 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2258 yyextra->newXRefKind = XRef_Test;
2259 setOutput(yyscanner,OutputXRef);
2260 yyextra->xrefKind = XRef_Test;
2264 static bool handleBug(yyscan_t yyscanner,const QCString &, const StringVector &)
2266 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2267 yyextra->newXRefKind = XRef_Bug;
2268 setOutput(yyscanner,OutputXRef);
2269 yyextra->xrefKind = XRef_Bug;
2273 static bool handleDeprecated(yyscan_t yyscanner,const QCString &, const StringVector &)
2275 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2276 yyextra->newXRefKind = XRef_Deprecated;
2277 setOutput(yyscanner,OutputXRef);
2278 yyextra->xrefKind = XRef_Deprecated;
2282 static bool handleXRefItem(yyscan_t yyscanner,const QCString &, const StringVector &)
2284 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2285 yyextra->newXRefKind = XRef_Item;
2286 BEGIN(XRefItemParam1);
2290 static bool handleParBlock(yyscan_t yyscanner,const QCString &, const StringVector &)
2292 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2293 if (yyextra->insideParBlock)
2295 warn(yyextra->fileName,yyextra->lineNr,
2296 "found \\parblock command while already in a parblock!");
2298 if (!yyextra->spaceBeforeCmd.isEmpty())
2300 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2301 yyextra->spaceBeforeCmd.resize(0);
2303 addOutput(yyscanner,"@parblock ");
2304 yyextra->insideParBlock = TRUE;
2308 static bool handleEndParBlock(yyscan_t yyscanner,const QCString &, const StringVector &)
2310 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2311 if (!yyextra->insideParBlock)
2313 warn(yyextra->fileName,yyextra->lineNr,
2314 "found \\endparblock command without matching \\parblock!");
2316 addOutput(yyscanner,"@endparblock");
2317 setOutput(yyscanner,OutputDoc); // to end a parblock inside a xrefitem like context
2318 yyextra->insideParBlock = FALSE;
2322 static bool handleRelated(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2324 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2325 if (!yyextra->current->relates.isEmpty())
2327 warn(yyextra->fileName,yyextra->lineNr,
2328 "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
2330 yyextra->current->relatesType = Simple;
2331 BEGIN(RelatesParam1);
2335 static bool handleRelatedAlso(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2337 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2338 if (!yyextra->current->relates.isEmpty())
2340 warn(yyextra->fileName,yyextra->lineNr,
2341 "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
2343 yyextra->current->relatesType = Duplicate;
2344 yyextra->currentCmd = cmd;
2345 BEGIN(RelatesParam1);
2349 static bool handleMemberOf(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2351 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2352 if (!yyextra->current->relates.isEmpty())
2354 warn(yyextra->fileName,yyextra->lineNr,
2355 "found multiple \\relates, \\relatesalso or \\memberof commands in a comment block, using last definition");
2357 yyextra->current->relatesType = MemberOf;
2358 yyextra->currentCmd = cmd;
2359 BEGIN(RelatesParam1);
2363 static bool handleRefItem(yyscan_t yyscanner,const QCString &, const StringVector &)
2365 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2366 addOutput(yyscanner,"@refitem ");
2371 static bool handleSection(yyscan_t yyscanner,const QCString &s, const StringVector &)
2373 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2374 setOutput(yyscanner,OutputDoc);
2375 addOutput(yyscanner,"@"+s+" ");
2376 BEGIN(SectionLabel);
2377 if (s=="section") yyextra->sectionLevel=1;
2378 else if (s=="subsection") yyextra->sectionLevel=2;
2379 else if (s=="subsubsection") yyextra->sectionLevel=3;
2380 else if (s=="paragraph") yyextra->sectionLevel=4;
2384 static bool handleSubpage(yyscan_t yyscanner,const QCString &s, const StringVector &)
2386 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2387 if (yyextra->current->section!=Entry::EMPTY_SEC &&
2388 yyextra->current->section!=Entry::PAGEDOC_SEC &&
2389 yyextra->current->section!=Entry::MAINPAGEDOC_SEC
2392 warn(yyextra->fileName,yyextra->lineNr,
2393 "found \\subpage command in a comment block that is not marked as a page!");
2395 if (!yyextra->spaceBeforeCmd.isEmpty())
2397 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2398 yyextra->spaceBeforeCmd.resize(0);
2400 addOutput(yyscanner,"@"+s+" ");
2401 BEGIN(SubpageLabel);
2405 static bool handleAnchor(yyscan_t yyscanner,const QCString &s, const StringVector &)
2407 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2408 addOutput(yyscanner,"@"+s+" ");
2413 static bool handleImage(yyscan_t yyscanner,const QCString &s, const StringVector &optList)
2415 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2416 for (const auto &opt : optList)
2418 QCString locOpt(opt);
2419 locOpt = locOpt.stripWhiteSpace();
2420 if (locOpt.lower().startsWith("anchor:"))
2422 addAnchor(yyscanner,locOpt.mid(7));
2423 break; // real option handling will be done later on
2426 if (optList.empty())
2428 addOutput(yyscanner,"@"+s+" ");
2432 addOutput(yyscanner,"@"+s+"{"+QCString(join(optList,","))+"} ");
2438 static bool handleCite(yyscan_t yyscanner,const QCString &s, const StringVector &)
2440 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2441 if (!yyextra->spaceBeforeCmd.isEmpty())
2443 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2444 yyextra->spaceBeforeCmd.resize(0);
2446 addOutput(yyscanner,"@"+s+" ");
2451 static bool handleFormatBlock(yyscan_t yyscanner,const QCString &s, const StringVector &optList)
2453 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2454 if (!yyextra->spaceBeforeCmd.isEmpty())
2456 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2457 yyextra->spaceBeforeCmd.resize(0);
2459 if (optList.empty())
2461 addOutput(yyscanner,"@"+s+" ");
2465 addOutput(yyscanner,"@"+s+"{"+QCString(join(optList,","))+"} ");
2467 //printf("handleFormatBlock(%s) with option(%s)\n",qPrint(s),qPrint(opt));
2468 yyextra->blockName=s;
2469 yyextra->commentCount=0;
2474 static bool handleAddIndex(yyscan_t yyscanner,const QCString &, const StringVector &)
2476 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2477 addOutput(yyscanner,"@addindex ");
2482 static bool handleIf(yyscan_t yyscanner,const QCString &, const StringVector &)
2484 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2485 yyextra->enabledSectionFound=FALSE;
2486 yyextra->guardType = Guard_If;
2487 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2492 static bool handleIfNot(yyscan_t yyscanner,const QCString &, const StringVector &)
2494 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2495 yyextra->enabledSectionFound=FALSE;
2496 yyextra->guardType = Guard_IfNot;
2497 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2502 static bool handleElseIf(yyscan_t yyscanner,const QCString &, const StringVector &)
2504 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2505 if (yyextra->guards.empty())
2507 warn(yyextra->fileName,yyextra->lineNr,
2508 "found \\else without matching start command");
2512 yyextra->guardType = yyextra->enabledSectionFound ? Guard_Skip : Guard_If;
2513 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2519 static bool handleElse(yyscan_t yyscanner,const QCString &, const StringVector &)
2521 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2522 if (yyextra->guards.empty())
2524 warn(yyextra->fileName,yyextra->lineNr,
2525 "found \\else without matching start command");
2529 yyextra->spaceBeforeIf = yyextra->spaceBeforeCmd;
2530 BEGIN( SkipGuardedSection );
2535 static bool handleEndIf(yyscan_t yyscanner,const QCString &, const StringVector &)
2537 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2538 if (yyextra->guards.empty())
2540 warn(yyextra->fileName,yyextra->lineNr,
2541 "found \\endif without matching start command");
2545 yyextra->guards.pop();
2547 yyextra->enabledSectionFound=FALSE;
2548 if (!yyextra->spaceBeforeCmd.isEmpty())
2550 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2551 yyextra->spaceBeforeCmd.resize(0);
2553 BEGIN( GuardParamEnd );
2557 static bool handleIngroup(yyscan_t yyscanner,const QCString &, const StringVector &)
2559 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2560 yyextra->inGroupParamFound=FALSE;
2561 BEGIN( InGroupParam );
2565 static bool handleNoSubGrouping(yyscan_t yyscanner,const QCString &, const StringVector &)
2567 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2568 yyextra->current->subGrouping = FALSE;
2572 static bool handleShowInitializer(yyscan_t yyscanner,const QCString &, const StringVector &)
2574 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2575 yyextra->current->initLines = 100000; // ON
2579 static bool handleHideInitializer(yyscan_t yyscanner,const QCString &, const StringVector &)
2581 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2582 yyextra->current->initLines = 0; // OFF
2586 static bool handleCallgraph(yyscan_t yyscanner,const QCString &, const StringVector &)
2588 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2589 yyextra->current->callGraph = TRUE; // ON
2593 static bool handleHideCallgraph(yyscan_t yyscanner,const QCString &, const StringVector &)
2595 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2596 yyextra->current->callGraph = FALSE; // OFF
2600 static bool handleCallergraph(yyscan_t yyscanner,const QCString &, const StringVector &)
2602 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2603 yyextra->current->callerGraph = TRUE; // ON
2607 static bool handleHideCallergraph(yyscan_t yyscanner,const QCString &, const StringVector &)
2609 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2610 yyextra->current->callerGraph = FALSE; // OFF
2614 static bool handleReferencedByRelation(yyscan_t yyscanner,const QCString &, const StringVector &)
2616 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2617 yyextra->current->referencedByRelation = TRUE; // ON
2621 static bool handleHideReferencedByRelation(yyscan_t yyscanner,const QCString &, const StringVector &)
2623 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2624 yyextra->current->referencedByRelation = FALSE; // OFF
2628 static bool handleReferencesRelation(yyscan_t yyscanner,const QCString &, const StringVector &)
2630 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2631 yyextra->current->referencesRelation = TRUE; // ON
2635 static bool handleHideReferencesRelation(yyscan_t yyscanner,const QCString &, const StringVector &)
2637 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2638 yyextra->current->referencesRelation = FALSE; // OFF
2642 static bool handleInternal(yyscan_t yyscanner,const QCString &, const StringVector &)
2644 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2645 if (!Config_getBool(INTERNAL_DOCS))
2647 // make sure some whitespace before a \internal command
2648 // is not treated as "documentation"
2649 if (yyextra->current->doc.stripWhiteSpace().isEmpty())
2651 yyextra->current->doc.resize(0);
2653 yyextra->condCount=0;
2654 BEGIN( SkipInternal );
2658 // re-enabled for bug640828
2659 addOutput(yyscanner," \\internal ");
2660 yyextra->inInternalDocs = TRUE;
2665 static bool handleStatic(yyscan_t yyscanner,const QCString &, const StringVector &)
2667 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2668 yyextra->current->stat = TRUE;
2672 static bool handlePure(yyscan_t yyscanner,const QCString &, const StringVector &)
2674 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2675 yyextra->current->virt = Pure;
2679 static bool handlePrivate(yyscan_t yyscanner,const QCString &, const StringVector &)
2681 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2682 yyextra->current->protection = Private;
2686 static bool handlePrivateSection(yyscan_t yyscanner,const QCString &, const StringVector &)
2688 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2689 yyextra->current->protection = yyextra->protection = Private;
2693 static bool handleProtected(yyscan_t yyscanner,const QCString &, const StringVector &)
2695 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2696 yyextra->current->protection = Protected;
2700 static bool handleProtectedSection(yyscan_t yyscanner,const QCString &, const StringVector &)
2702 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2703 yyextra->current->protection = yyextra->protection = Protected ;
2707 static bool handlePublic(yyscan_t yyscanner,const QCString &, const StringVector &)
2709 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2710 yyextra->current->protection = Public;
2714 static bool handlePublicSection(yyscan_t yyscanner,const QCString &, const StringVector &)
2716 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2717 yyextra->current->protection = yyextra->protection = Public;
2721 static bool handleToc(yyscan_t yyscanner,const QCString &, const StringVector &optList)
2723 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2724 if (yyextra->current->section==Entry::PAGEDOC_SEC ||
2725 yyextra->current->section==Entry::MAINPAGEDOC_SEC)
2727 for (const auto &opt_ : optList)
2729 QCString opt = QCString(opt_).stripWhiteSpace().lower();
2732 int i = opt.find(':');
2733 if (i>0) // found ':' but not on position 0 what would mean just a level
2735 if (sscanf(opt.right(opt.length() - i - 1).data(),"%d%c",&level,&dum) != 1)
2737 warn(yyextra->fileName,yyextra->lineNr,"Unknown option:level specified with \\tableofcontents: '%s'", qPrint(QCString(opt_).stripWhiteSpace()));
2742 level = (level > 5 ? 5 : level);
2743 level = (level <= 0 ? 5 : level);
2744 opt = opt.left(i).stripWhiteSpace();
2751 yyextra->current->localToc.enableHtml(level);
2753 else if (opt == "latex")
2755 yyextra->current->localToc.enableLatex(level);
2757 else if (opt == "xml")
2759 yyextra->current->localToc.enableXml(level);
2761 else if (opt == "docbook")
2763 yyextra->current->localToc.enableDocbook(level);
2767 warn(yyextra->fileName,yyextra->lineNr,"Unknown option specified with \\tableofcontents: '%s'", qPrint(QCString(opt_).stripWhiteSpace()));
2771 if (yyextra->current->localToc.nothingEnabled())
2773 // for backward compatibility
2774 yyextra->current->localToc.enableHtml(5);
2775 yyextra->current->localToc.enableXml(5);
2781 static bool handleInherit(yyscan_t yyscanner,const QCString &, const StringVector &)
2783 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2784 BEGIN(InheritParam);
2788 static bool handleExtends(yyscan_t yyscanner,const QCString &cmd, const StringVector &)
2790 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2791 yyextra->currentCmd = cmd;
2792 BEGIN(ExtendsParam);
2796 static bool handleCopyBrief(yyscan_t yyscanner,const QCString &, const StringVector &)
2798 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2799 if (yyextra->current->brief.isEmpty() && yyextra->current->doc.isEmpty())
2800 { // if we don't have a brief or detailed description yet,
2801 // then the @copybrief should end up in the brief description.
2802 // otherwise it will be copied inline (see bug691315 & bug700788)
2803 setOutput(yyscanner,OutputBrief);
2805 if (!yyextra->spaceBeforeCmd.isEmpty())
2807 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2808 yyextra->spaceBeforeCmd.resize(0);
2810 addOutput(yyscanner,"\\copybrief ");
2814 static bool handleCopyDetails(yyscan_t yyscanner,const QCString &, const StringVector &)
2816 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2817 setOutput(yyscanner,OutputDoc);
2818 if (!yyextra->spaceBeforeCmd.isEmpty())
2820 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2821 yyextra->spaceBeforeCmd.resize(0);
2823 addOutput(yyscanner,"\\copydetails ");
2827 static bool handleCopyDoc(yyscan_t yyscanner,const QCString &, const StringVector &)
2829 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2830 setOutput(yyscanner,OutputBrief);
2831 if (!yyextra->spaceBeforeCmd.isEmpty())
2833 addOutput(yyscanner,yyextra->spaceBeforeCmd);
2834 yyextra->spaceBeforeCmd.resize(0);
2836 addOutput(yyscanner,"\\copybrief ");
2837 yyextra->copyDocArg.resize(0);
2842 //-----------------------------------------------------------------------------------------
2844 static void initParser(yyscan_t yyscanner)
2846 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2847 yyextra->sectionLabel.resize(0);
2848 yyextra->sectionTitle.resize(0);
2849 yyextra->docGroup.clearHeader();
2850 yyextra->insideParBlock = FALSE;
2854 static bool getDocSectionName(int s)
2858 case Entry::CLASSDOC_SEC:
2859 case Entry::STRUCTDOC_SEC:
2860 case Entry::UNIONDOC_SEC:
2861 case Entry::EXCEPTIONDOC_SEC:
2862 case Entry::NAMESPACEDOC_SEC:
2863 case Entry::PROTOCOLDOC_SEC:
2864 case Entry::CATEGORYDOC_SEC:
2865 case Entry::ENUMDOC_SEC:
2866 case Entry::PAGEDOC_SEC:
2867 case Entry::VARIABLEDOC_SEC:
2868 case Entry::MEMBERDOC_SEC:
2869 case Entry::OVERLOADDOC_SEC:
2870 case Entry::FILEDOC_SEC:
2871 case Entry::DEFINEDOC_SEC:
2872 case Entry::GROUPDOC_SEC:
2873 case Entry::MAINPAGEDOC_SEC:
2874 case Entry::PACKAGEDOC_SEC:
2875 case Entry::DIRDOC_SEC:
2876 case Entry::EXAMPLE_SEC:
2877 case Entry::MEMBERGRP_SEC:
2878 case Entry::CONCEPTDOC_SEC:
2885 //-----------------------------------------------------------------------------
2887 static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s)
2889 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2890 //printf("yyextra->current->section=%x\n",yyextra->current->section);
2891 if (getDocSectionName(yyextra->current->section))
2897 yyextra->needNewEntry = TRUE;
2898 yyextra->current->section = s;
2899 yyextra->current->fileName = yyextra->fileName;
2900 yyextra->current->startLine = yyextra->lineNr;
2901 yyextra->current->docLine = yyextra->lineNr;
2906 //-----------------------------------------------------------------
2908 static void lineCount(yyscan_t yyscanner)
2910 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2911 for( const char* c = yytext ; *c ; ++c )
2912 yyextra->lineNr += (*c == '\n') ;
2915 //-----------------------------------------------------------------
2917 static QCString stripQuotes(const char *s)
2920 if (s==0 || *s==0) return name;
2922 if (name.at(0)=='"' && name.at(name.length()-1)=='"')
2924 name=name.mid(1,name.length()-2);
2929 //-----------------------------------------------------------------
2931 static void addXRefItem(yyscan_t yyscanner,
2932 const QCString &listName,const QCString &itemTitle,
2933 const QCString &listTitle,bool append)
2935 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2936 if (listName.isEmpty()) return;
2937 //printf("addXRefItem(%s,%s,%s,%d)\n",listName,itemTitle,listTitle,append);
2939 std::unique_lock<std::mutex> lock(g_sectionMutex);
2941 RefList *refList = RefListManager::instance().add(listName,listTitle,itemTitle);
2943 for (auto it = yyextra->current->sli.rbegin(); it != yyextra->current->sli.rend(); ++it)
2946 if (i && i->list()->listName()==listName)
2948 //printf("found %s lii->type=%s\n",listName,qPrint(i->list()->listName()));
2953 if (item && append) // already found item of same type just before this one
2955 //printf("listName=%s item id = %d existing\n",listName,item->id());
2956 item->setText(item->text() + " <p>" + yyextra->outputXRef);
2957 //printf("%s: text +=%s\n",listName,qPrint(item->text));
2962 // if we have already an item from the same list type (e.g. a second @todo)
2963 // in the same Entry (i.e. lii!=0) then we reuse its link anchor.
2964 item = refList->add();
2965 //printf("listName=%s item id = %d new yyextra->current=%p\n",listName,item->id(),yyextra->current);
2966 QCString anchorLabel;
2967 anchorLabel.sprintf("_%s%06d",listName.data(),item->id());
2968 item->setText(yyextra->outputXRef);
2969 item->setAnchor(anchorLabel);
2970 yyextra->current->sli.push_back(item);
2972 cmdString.sprintf(" \\xrefitem %s %d.",qPrint(listName),item->id());
2973 if (yyextra->inBody)
2975 yyextra->current->inbodyDocs += cmdString;
2979 yyextra->current->doc += cmdString;
2983 SectionManager &sm = SectionManager::instance();
2984 const SectionInfo *si = sm.find(anchorLabel);
2987 if (!si->ref().isEmpty()) // we are from a tag file
2989 si = sm.replace(anchorLabel,listName,yyextra->lineNr,
2990 yyextra->sectionTitle,SectionType::Anchor,
2991 yyextra->sectionLevel);
2992 yyextra->current->anchors.push_back(si);
2994 else if (si->lineNr() != -1)
2996 warn(listName,yyextra->lineNr,"multiple use of section label '%s', (first occurrence: %s, line %d)",qPrint(anchorLabel),qPrint(si->fileName()),si->lineNr());
3000 warn(listName,yyextra->lineNr,"multiple use of section label '%s', (first occurrence: %s)",qPrint(anchorLabel),qPrint(si->fileName()));
3005 si = sm.add(anchorLabel,listName,yyextra->lineNr,
3006 yyextra->sectionTitle,SectionType::Anchor,
3007 yyextra->sectionLevel);
3008 yyextra->current->anchors.push_back(si);
3012 yyextra->outputXRef.resize(0);
3015 //-----------------------------------------------------------------------------
3017 // Adds a formula text to the list/dictionary of formulas if it was
3018 // not already added. Returns the label of the formula.
3019 static QCString addFormula(yyscan_t yyscanner)
3021 std::unique_lock<std::mutex> lock(g_formulaMutex);
3022 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3024 QCString fText=yyextra->formulaText.simplifyWhiteSpace();
3025 int id = FormulaManager::instance().addFormula(fText.str());
3026 formLabel.sprintf("\\_form#%d",id);
3027 for (int i=0;i<yyextra->formulaNewLines;i++) formLabel+="@_fakenl"; // add fake newlines to
3028 // keep the warnings
3029 // correctly aligned.
3033 //-----------------------------------------------------------------------------
3035 static SectionType sectionLevelToType(int level)
3037 if (level>=0 && level<5) return (SectionType)level;
3038 return SectionType::Anchor;
3041 static void addSection(yyscan_t yyscanner)
3043 std::unique_lock<std::mutex> lock(g_sectionMutex);
3044 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3045 SectionManager &sm = SectionManager::instance();
3046 const SectionInfo *si = sm.find(yyextra->sectionLabel);
3049 if (!si->ref().isEmpty()) // we are from a tag file
3051 // create a new section element
3052 yyextra->sectionTitle+=yytext;
3053 yyextra->sectionTitle=yyextra->sectionTitle.stripWhiteSpace();
3054 si = sm.replace(yyextra->sectionLabel,yyextra->fileName,yyextra->lineNr,
3055 yyextra->sectionTitle,sectionLevelToType(yyextra->sectionLevel),
3056 yyextra->sectionLevel);
3058 // add section to this entry
3059 yyextra->current->anchors.push_back(si);
3061 else if (si->lineNr() != -1)
3063 warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s, line %d)",qPrint(yyextra->sectionLabel),qPrint(si->fileName()),si->lineNr());
3067 warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding section, (first occurrence: %s)",qPrint(yyextra->sectionLabel),qPrint(si->fileName()));
3072 // create a new section element
3073 yyextra->sectionTitle+=yytext;
3074 yyextra->sectionTitle=yyextra->sectionTitle.stripWhiteSpace();
3075 si = sm.add(yyextra->sectionLabel,yyextra->fileName,yyextra->lineNr,
3076 yyextra->sectionTitle,sectionLevelToType(yyextra->sectionLevel),
3077 yyextra->sectionLevel);
3079 // add section to this entry
3080 yyextra->current->anchors.push_back(si);
3084 //-----------------------------------------------------------------------------
3086 static void addCite(yyscan_t yyscanner)
3088 std::unique_lock<std::mutex> lock(g_citeMutex);
3089 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3090 QCString name(yytext);
3091 if (yytext[0] =='"')
3094 name=name.left((int)yyleng-2);
3096 CitationManager::instance().insert(name);
3099 //-----------------------------------------------------------------------------
3101 // strip trailing whitespace (excluding newlines) from string s
3102 static void stripTrailingWhiteSpace(QCString &s)
3104 uint len = s.length();
3110 if (c==' ' || c=='\t' || c=='\r') // normal whitespace
3114 else if (c=='r' && i>=7 && qstrncmp("\\ilinebr",s.data()+i-7,8)==0) // special line break marker
3118 else // non-whitespace
3123 //printf("stripTrailingWhitespace(%s) i=%d len=%d\n",qPrint(s),i,len);
3126 s.resize(i+2); // string up to and including char at pos i and \0 terminator
3130 // selects the output to write to
3131 static inline void setOutput(yyscan_t yyscanner,OutputContext ctx)
3133 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3134 bool xrefAppendToPrev = yyextra->xrefAppendFlag;
3135 // determine append flag for the next item (i.e. the end of this item)
3136 yyextra->xrefAppendFlag = !yyextra->inBody &&
3137 yyextra->inContext==OutputXRef && ctx==OutputXRef && // two consecutive xref items
3138 yyextra->newXRefKind==yyextra->xrefKind && // of the same kind
3139 (yyextra->xrefKind!=XRef_Item ||
3140 yyextra->newXRefItemKey==yyextra->xrefItemKey); // with the same key if \xrefitem
3141 //printf("%d && %d && %d && (%d || %d)\n",
3142 // yyextra->inContext==OutputXRef,
3144 // yyextra->newXRefKind==yyextra->xrefKind,
3145 // yyextra->xrefKind!=XRef_Item,
3146 // yyextra->newXRefItemKey==yyextra->xrefItemKey);
3147 //printf("refKind=%d yyextra->newXRefKind=%d xrefAppendToPrev=%d yyextra->xrefAppendFlag=%d\n",
3148 // yyextra->xrefKind,yyextra->newXRefKind,xrefAppendToPrev,yyextra->xrefAppendFlag);
3150 //printf("setOutput(yyscanner,yyextra->inContext=%d ctx=%d)\n",yyextra->inContext,ctx);
3151 if (yyextra->inContext==OutputXRef) // end of XRef section => add the item
3153 // See if we can append this new xref item to the previous one.
3154 // We know this at the start of the next item of the same
3155 // type and need to remember this until the end of that item.
3156 switch(yyextra->xrefKind)
3159 addXRefItem(yyscanner,QCString("todo"),
3160 theTranslator->trTodo(),
3161 theTranslator->trTodoList(),
3166 addXRefItem(yyscanner,QCString("test"),
3167 theTranslator->trTest(),
3168 theTranslator->trTestList(),
3173 addXRefItem(yyscanner,QCString("bug"),
3174 theTranslator->trBug(),
3175 theTranslator->trBugList(),
3179 case XRef_Deprecated:
3180 addXRefItem(yyscanner,QCString("deprecated"),
3181 theTranslator->trDeprecated(),
3182 theTranslator->trDeprecatedList(),
3186 case XRef_Item: // user defined list
3187 addXRefItem(yyscanner,yyextra->xrefItemKey,
3188 yyextra->xrefItemTitle,
3189 yyextra->xrefListTitle,
3198 yyextra->xrefItemKey = yyextra->newXRefItemKey;
3200 int oldContext = yyextra->inContext;
3201 yyextra->inContext = ctx;
3202 if (yyextra->inContext!=OutputXRef && yyextra->inBody) yyextra->inContext=OutputInbody;
3203 switch(yyextra->inContext)
3206 if (oldContext!=yyextra->inContext)
3208 stripTrailingWhiteSpace(yyextra->current->doc);
3209 if (yyextra->current->doc.isEmpty()) yyextra->current->docLine = yyextra->lineNr;
3210 if (yyextra->current->docFile.isEmpty())
3212 yyextra->current->docFile = yyextra->fileName;
3213 yyextra->current->docLine = yyextra->lineNr;
3216 yyextra->pOutputString = &yyextra->current->doc;
3219 if (oldContext!=yyextra->inContext)
3221 if (yyextra->current->brief.isEmpty()) yyextra->current->briefLine = yyextra->lineNr;
3222 if (yyextra->current->briefFile.isEmpty())
3224 yyextra->current->briefFile = yyextra->fileName;
3225 yyextra->current->briefLine = yyextra->lineNr;
3228 if (yyextra->current->brief.stripWhiteSpace().isEmpty()) // we only want one brief
3229 // description even if multiple
3232 yyextra->pOutputString = &yyextra->current->brief;
3236 if (!yyextra->current->doc.isEmpty()) // when appending parts add a new line
3238 yyextra->current->doc += "\n";
3240 yyextra->pOutputString = &yyextra->current->doc;
3241 yyextra->inContext = OutputDoc; // need to switch to detailed docs, see bug 631380
3245 yyextra->pOutputString = &yyextra->outputXRef;
3246 // first item found, so can't append to previous
3247 //yyextra->xrefAppendFlag = FALSE;
3250 yyextra->pOutputString = &yyextra->current->inbodyDocs;
3256 static void addAnchor(yyscan_t yyscanner,const QCString &anchor)
3258 std::unique_lock<std::mutex> lock(g_sectionMutex);
3259 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3260 SectionManager &sm = SectionManager::instance();
3261 const SectionInfo *si = sm.find(anchor);
3264 if (!si->ref().isEmpty()) // we are from a tag file
3266 si = sm.replace(anchor,yyextra->fileName,yyextra->lineNr,QCString(),SectionType::Anchor,0);
3267 yyextra->current->anchors.push_back(si);
3269 else if (si->lineNr() != -1)
3271 warn(yyextra->fileName,yyextra->lineNr,
3272 "multiple use of section label '%s' while adding anchor, (first occurrence: %s, line %d)",
3273 qPrint(anchor),qPrint(si->fileName()),si->lineNr());
3277 warn(yyextra->fileName,yyextra->lineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s)",
3278 qPrint(anchor),qPrint(si->fileName()));
3283 si = sm.add(anchor,yyextra->fileName,yyextra->lineNr,QCString(),SectionType::Anchor,0);
3284 yyextra->current->anchors.push_back(si);
3288 // add a string to the output
3289 static inline void addOutput(yyscan_t yyscanner,const char *s)
3291 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3292 //printf("addOutput(yyscanner,%s)\n",s);
3293 *yyextra->pOutputString+=s;
3296 // add a string to the output
3297 static inline void addOutput(yyscan_t yyscanner,const QCString &s)
3299 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3300 //printf("addOutput(yyscanner,%s)\n",s);
3301 *yyextra->pOutputString+=s;
3304 // add a character to the output
3305 static inline void addOutput(yyscan_t yyscanner,char c)
3307 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3308 *yyextra->pOutputString+=c;
3311 static void addIline(yyscan_t yyscanner,int lineNr)
3314 sprintf(cmd,"\\iline %d ",lineNr);
3315 addOutput(yyscanner, cmd);
3318 static void endBrief(yyscan_t yyscanner,bool addToOutput)
3320 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3321 if (!yyextra->current->brief.stripWhiteSpace().isEmpty())
3322 { // only go to the detailed description if we have
3323 // found some brief description and not just whitespace
3324 yyextra->briefEndsAtDot=FALSE;
3325 setOutput(yyscanner,OutputDoc);
3326 if (addToOutput) addOutput(yyscanner,yytext);
3330 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
3332 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3333 yyextra->prevPosition=yyextra->inputPosition;
3335 while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
3337 *buf = yyextra->inputString[yyextra->inputPosition++] ;
3338 //printf("%d (%c)\n",*buf,*buf);
3344 //----------------------------------------------------------------------------
3346 static void checkFormula(yyscan_t yyscanner)
3348 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3349 if (YY_START==ReadFormulaShort || YY_START==ReadFormulaRound || YY_START==ReadFormulaLong)
3351 warn(yyextra->fileName,yyextra->lineNr,"End of comment block while inside formula.");
3355 //----------------------------------------------------------------------------
3357 struct CommentScanner::Private
3360 commentscanYY_state extra;
3363 CommentScanner::CommentScanner() : p(std::make_unique<Private>())
3365 commentscanYYlex_init_extra(&p->extra,&p->yyscanner);
3367 commentscanYYset_debug(1,p->yyscanner);
3371 CommentScanner::~CommentScanner()
3373 commentscanYYlex_destroy(p->yyscanner);
3376 bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *parser,
3377 /* in */ Entry *curEntry,
3378 /* in */ const QCString &comment,
3379 /* in */ const QCString &fileName,
3380 /* in,out */ int &lineNr,
3381 /* in */ bool isBrief,
3382 /* in */ bool isAutoBriefOn,
3383 /* in */ bool isInbody,
3384 /* in,out */ Protection &prot,
3385 /* in,out */ int &position,
3386 /* out */ bool &newEntryNeeded,
3387 /* in */ bool markdownSupport
3390 yyscan_t yyscanner = p->yyscanner;
3391 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3392 //printf("parseCommentBlock() isBrief=%d isAutoBriefOn=%d lineNr=%d\n",
3393 // isBrief,isAutoBriefOn,lineNr);
3395 initParser(yyscanner);
3396 yyextra->guards = std::stack<GuardedSection>();
3397 yyextra->langParser = parser;
3398 yyextra->current = curEntry;
3399 yyextra->current->docLine = (lineNr > 1 ? lineNr : 1);
3400 if (comment.isEmpty()) return FALSE; // avoid empty strings
3401 yyextra->inputString = comment;
3402 yyextra->inputString.append(" ");
3403 yyextra->inputPosition = position;
3404 yyextra->lineNr = lineNr;
3405 yyextra->fileName = fileName;
3406 yyextra->protection = prot;
3407 yyextra->needNewEntry = FALSE;
3408 yyextra->xrefKind = XRef_None;
3409 yyextra->xrefAppendFlag = FALSE;
3410 yyextra->insidePre = FALSE;
3411 yyextra->parseMore = FALSE;
3412 yyextra->inBody = isInbody;
3413 yyextra->markdownSupport= markdownSupport;
3414 yyextra->outputXRef.resize(0);
3415 if (!isBrief && !isAutoBriefOn && !yyextra->current->doc.isEmpty())
3416 { // add newline separator between detailed comment blocks
3417 yyextra->current->doc += '\n';
3419 setOutput(yyscanner, isBrief || isAutoBriefOn ? OutputBrief : OutputDoc );
3420 yyextra->briefEndsAtDot = isAutoBriefOn;
3421 yyextra->condCount = 0;
3422 yyextra->sectionLevel = 0;
3423 yyextra->spaceBeforeCmd.resize(0);
3424 yyextra->spaceBeforeIf.resize(0);
3426 printlex(yy_flex_debug, TRUE, __FILE__, !fileName.isEmpty() ? qPrint(fileName): NULL);
3427 if (!yyextra->current->inbodyDocs.isEmpty() && isInbody) // separate in body fragments
3429 yyextra->current->inbodyDocs+="\n\n";
3432 Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\n"
3433 "input=[\n%s]\n",qPrint(fileName),lineNr,qPrint(yyextra->inputString)
3436 commentscanYYrestart( 0, yyscanner );
3438 commentscanYYlex(yyscanner);
3439 setOutput(yyscanner, OutputDoc );
3441 if (YY_START==OverloadParam) // comment ended with \overload
3443 addOutput(yyscanner,getOverloadDocs());
3446 if (!yyextra->guards.empty())
3448 warn(yyextra->fileName,yyextra->lineNr,"Documentation block ended in the middle of a conditional section!");
3451 if (yyextra->insideParBlock)
3453 warn(yyextra->fileName,yyextra->lineNr,
3454 "Documentation block ended while inside a \\parblock. Missing \\endparblock");
3457 yyextra->current->doc=stripLeadingAndTrailingEmptyLines(yyextra->current->doc,yyextra->current->docLine);
3459 if (yyextra->current->section==Entry::FILEDOC_SEC && yyextra->current->doc.isEmpty())
3461 // to allow a comment block with just a @file command.
3462 yyextra->current->doc="\n\n";
3465 if (yyextra->current->section==Entry::MEMBERGRP_SEC &&
3466 yyextra->docGroup.isEmpty()) // @name section but no group started yet
3468 yyextra->docGroup.open(yyextra->current,yyextra->fileName,yyextra->lineNr,true);
3471 Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\noutput=[\n"
3472 "brief=[line=%d\n%s]\ndocs=[line=%d\n%s]\ninbody=[line=%d\n%s]\n]\n===========\n",
3473 qPrint(fileName),lineNr,
3474 yyextra->current->briefLine,qPrint(yyextra->current->brief),
3475 yyextra->current->docLine,qPrint(yyextra->current->doc),
3476 yyextra->current->inbodyLine,qPrint(yyextra->current->inbodyDocs)
3479 checkFormula(yyscanner);
3480 prot = yyextra->protection;
3482 yyextra->docGroup.addDocs(curEntry);
3484 newEntryNeeded = yyextra->needNewEntry;
3486 // if we did not proceed during this call, it does not make
3487 // sense to continue, since we get stuck. See bug 567346 for situations
3488 // were this happens
3489 if (yyextra->parseMore && position==yyextra->inputPosition) yyextra->parseMore=FALSE;
3491 if (yyextra->parseMore) position=yyextra->inputPosition; else position=0;
3493 lineNr = yyextra->lineNr;
3494 //printf("position=%d yyextra->parseMore=%d newEntryNeeded=%d\n",
3495 // position,yyextra->parseMore,newEntryNeeded);
3497 printlex(yy_flex_debug, FALSE, __FILE__, !fileName.isEmpty() ? qPrint(fileName): NULL);
3498 return yyextra->parseMore;
3501 static void handleGuard(yyscan_t yyscanner,const QCString &expr)
3503 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3505 bool sectionEnabled=prs.parse(yyextra->fileName,yyextra->lineNr,expr.stripWhiteSpace());
3506 bool parentEnabled = TRUE;
3507 if (!yyextra->guards.empty()) parentEnabled = yyextra->guards.top().isEnabled();
3511 (sectionEnabled && yyextra->guardType==Guard_If) ||
3512 (!sectionEnabled && yyextra->guardType==Guard_IfNot)
3513 ) // section is visible
3515 yyextra->guards.push(GuardedSection(TRUE,TRUE));
3516 yyextra->enabledSectionFound=TRUE;
3517 BEGIN( GuardParamEnd );
3519 else // section is invisible
3521 if (yyextra->guardType!=Guard_Skip)
3523 yyextra->guards.push(GuardedSection(FALSE,TRUE));
3525 BEGIN( SkipGuardedSection );
3528 else // invisible because of parent
3530 yyextra->guards.push(GuardedSection(FALSE,FALSE));
3531 BEGIN( SkipGuardedSection );
3535 void CommentScanner::initGroupInfo(Entry *entry)
3537 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3538 yyextra->docGroup.initGroupInfo(entry);
3541 void CommentScanner::enterFile(const QCString &fileName,int lineNr)
3543 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3544 yyextra->docGroup.enterFile(fileName,lineNr);
3547 void CommentScanner::leaveFile(const QCString &fileName,int lineNr)
3549 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3550 yyextra->docGroup.leaveFile(fileName,lineNr);
3553 void CommentScanner::enterCompound(const QCString &fileName,int lineNr,const QCString &name)
3555 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3556 yyextra->docGroup.enterCompound(fileName,lineNr,name);
3559 void CommentScanner::leaveCompound(const QCString &fileName,int lineNr,const QCString &name)
3561 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3562 yyextra->docGroup.leaveCompound(fileName,lineNr,name);
3565 void CommentScanner::open(Entry *e,const QCString &fileName,int lineNr,bool implicit)
3567 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3568 yyextra->docGroup.open(e,fileName,lineNr,implicit);
3571 void CommentScanner::close(Entry *e,const QCString &fileName,int lineNr,bool foundInline,bool implicit)
3573 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
3574 yyextra->docGroup.close(e,fileName,lineNr,foundInline,implicit);
3577 #if USE_STATE2STRING
3578 #include "commentscan.l.h"