Doxygen
Loading...
Searching...
No Matches
DocParser Class Reference

#include <src/docparser_p.h>

Inheritance diagram for DocParser:
Collaboration diagram for DocParser:

Public Member Functions

void pushContext ()
void popContext ()
void handleImg (DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
Token internalValidatingParseDoc (DocNodeVariant *parent, DocNodeList &children, const QCString &doc)
QCString processCopyDoc (const char *data, size_t &len)
QCString findAndCopyImage (const QCString &fileName, DocImage::Type type, bool doWarn=true)
void checkArgumentName ()
void checkRetvalName ()
void checkUnOrMultipleDocumentedParams ()
bool findDocsForMemberOrCompound (const QCString &commandName, QCString *pDoc, QCString *pBrief, const Definition **pDef)
bool defaultHandleToken (DocNodeVariant *parent, Token tok, DocNodeList &children, bool handleWord=TRUE)
void errorHandleDefaultToken (DocNodeVariant *parent, Token tok, DocNodeList &children, const QCString &txt)
void defaultHandleTitleAndSize (const CommandType cmd, DocNodeVariant *parent, DocNodeList &children, QCString &width, QCString &height)
Token handleStyleArgument (DocNodeVariant *parent, DocNodeList &children, const QCString &cmdName)
void handleStyleEnter (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName, const HtmlAttribList *attribs)
void handleStyleLeave (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName)
void handlePendingStyleCommands (DocNodeVariant *parent, DocNodeList &children)
void handleInitialStyleCommands (DocNodeVariant *parent, DocNodeList &children)
Token handleAHref (DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
void handleUnclosedStyleCommands ()
void handleLinkedWord (DocNodeVariant *parent, DocNodeList &children, bool ignoreAutoLinkFlag=FALSE)
void handleParameterType (DocNodeVariant *parent, DocNodeList &children, const QCString &paramTypes)
void handleInternalRef (DocNodeVariant *parent, DocNodeList &children)
void handleAnchor (DocNodeVariant *parent, DocNodeList &children)
void handlePrefix (DocNodeVariant *parent, DocNodeList &children)
void handleImage (DocNodeVariant *parent, DocNodeList &children)
void readTextFileByName (const QCString &file, QCString &text)

Public Attributes

std::stack< DocParserContextcontextStack
DocParserContext context
DocTokenizer tokenizer

Detailed Description

Definition at line 99 of file docparser_p.h.

Member Function Documentation

◆ checkArgumentName()

void DocParser::checkArgumentName ( )

Collects the parameters found with @param command in a list context.paramsFound. If the parameter is not an actual parameter of the current member context.memberDef, then a warning is raised (unless warnings are disabled altogether).

Definition at line 208 of file docparser.cpp.

209{
210 if (!(Config_getBool(WARN_IF_DOC_ERROR) || Config_getBool(WARN_IF_INCOMPLETE_DOC))) return;
211 if (context.memberDef==nullptr) return; // not a member
212 std::string name = context.token->name.str();
213 const ArgumentList &al=context.memberDef->isDocsForDefinition() ?
214 context.memberDef->argumentList() :
215 context.memberDef->declArgumentList();
216 SrcLangExt lang = context.memberDef->getLanguage();
217 //printf("isDocsForDefinition()=%d\n",context.memberDef->isDocsForDefinition());
218 if (al.empty()) return; // no argument list
219
220 static const reg::Ex re(R"(\$?\w+\.*)");
221 reg::Iterator it(name,re);
222 reg::Iterator end;
223 for (; it!=end ; ++it)
224 {
225 const auto &match = *it;
226 QCString aName=match.str();
227 if (lang==SrcLangExt::Fortran) aName=aName.lower();
228 //printf("aName='%s'\n",qPrint(aName));
229 bool found=FALSE;
230 for (const Argument &a : al)
231 {
232 QCString argName = context.memberDef->isDefine() ? a.type : a.name;
233 if (lang==SrcLangExt::Fortran) argName=argName.lower();
234 argName=argName.stripWhiteSpace();
235 //printf("argName='%s' aName=%s\n",qPrint(argName),qPrint(aName));
236 if (argName.endsWith("...")) argName=argName.left(argName.length()-3);
237 if (aName==argName)
238 {
239 context.paramsFound.insert(aName.str());
240 found=TRUE;
241 break;
242 }
243 }
244 if (!found)
245 {
246 //printf("member type=%d\n",context.memberDef->memberType());
247 QCString scope=context.memberDef->getScopeString();
248 if (!scope.isEmpty()) scope+="::"; else scope="";
249 QCString inheritedFrom = "";
250 QCString docFile = context.memberDef->docFile();
251 int docLine = context.memberDef->docLine();
252 const MemberDef *inheritedMd = context.memberDef->inheritsDocsFrom();
253 if (inheritedMd) // documentation was inherited
254 {
255 inheritedFrom.sprintf(" inherited from member %s at line "
256 "%d in file %s",qPrint(inheritedMd->name()),
257 inheritedMd->docLine(),qPrint(inheritedMd->docFile()));
258 docFile = context.memberDef->getDefFileName();
259 docLine = context.memberDef->getDefLine();
260 }
261 QCString alStr = argListToString(al);
262 warn_doc_error(docFile,docLine,
263 "argument '{}' of command @param "
264 "is not found in the argument list of {}{}{}{}",
265 aName, scope, context.memberDef->name(),
266 alStr, inheritedFrom);
267 }
268 }
269}
bool empty() const
Definition arguments.h:99
virtual QCString docFile() const =0
virtual int docLine() const =0
virtual const QCString & name() const =0
DocParserContext context
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
QCString lower() const
Definition qcstring.h:234
bool endsWith(const char *s) const
Definition qcstring.h:509
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
const std::string & str() const
Definition qcstring.h:537
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
QCString left(size_t len) const
Definition qcstring.h:214
#define Config_getBool(name)
Definition config.h:33
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
#define warn_doc_error(file, line, fmt,...)
Definition message.h:112
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:759
const char * qPrint(const char *s)
Definition qcstring.h:672
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
SrcLangExt
Definition types.h:207
QCString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:1202

References argListToString(), Config_getBool, context, Definition::docFile(), Definition::docLine(), ArgumentList::empty(), end(), QCString::endsWith(), FALSE, QCString::isEmpty(), QCString::left(), QCString::length(), QCString::lower(), Definition::name(), qPrint(), QCString::sprintf(), QCString::str(), QCString::stripWhiteSpace(), TRUE, and warn_doc_error.

Referenced by DocParamList::parse(), and DocParamList::parseXml().

◆ checkRetvalName()

void DocParser::checkRetvalName ( )

Collects the return values found with @retval command in a global list g_parserContext.retvalsFound.

Definition at line 273 of file docparser.cpp.

274{
275 QCString name = context.token->name;
276 if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
277 if (context.memberDef==nullptr || name.isEmpty()) return; // not a member or no valid name
278 if (context.retvalsFound.count(name.str())==1) // only report the first double entry
279 {
280 warn_doc_error(context.memberDef->getDefFileName(),
281 context.memberDef->getDefLine(),
282 "return value '{}' of {} has multiple documentation sections",
283 name, context.memberDef->qualifiedName());
284 }
285 context.retvalsFound.insert(name.str());
286}

References Config_getBool, context, QCString::isEmpty(), QCString::str(), and warn_doc_error.

Referenced by DocParamList::parse(), and DocParamList::parseXml().

◆ checkUnOrMultipleDocumentedParams()

void DocParser::checkUnOrMultipleDocumentedParams ( )

Checks if the parameters that have been specified using @param are indeed all parameters and that a parameter does not have multiple @param blocks. Must be called after checkArgumentName() has been called for each argument.

Definition at line 294 of file docparser.cpp.

295{
296 if (context.memberDef && context.hasParamCommand)
297 {
298 const ArgumentList &al=context.memberDef->isDocsForDefinition() ?
299 context.memberDef->argumentList() :
300 context.memberDef->declArgumentList();
301 SrcLangExt lang = context.memberDef->getLanguage();
302 if (!al.empty())
303 {
304 ArgumentList undocParams;
305 for (const Argument &a: al)
306 {
307 QCString argName = context.memberDef->isDefine() ? a.type : a.name;
308 if (lang==SrcLangExt::Fortran) argName = argName.lower();
309 argName=argName.stripWhiteSpace();
310 QCString aName = argName;
311 if (argName.endsWith("...")) argName=argName.left(argName.length()-3);
312 if (lang==SrcLangExt::Python && (argName=="self" || argName=="cls"))
313 {
314 // allow undocumented self / cls parameter for Python
315 }
316 else if (lang==SrcLangExt::Cpp && (a.type=="this" || a.type.startsWith("this ")))
317 {
318 // allow undocumented this (for C++23 deducing this), see issue #11123
319 }
320 else if (!argName.isEmpty())
321 {
322 size_t count = context.paramsFound.count(argName.str());
323 if (count==0 && a.docs.isEmpty())
324 {
325 undocParams.push_back(a);
326 }
327 else if (count>1 && Config_getBool(WARN_IF_DOC_ERROR))
328 {
329 warn_doc_error(context.memberDef->docFile(),
330 context.memberDef->docLine(),
331 "argument {} from the argument list of {} has multiple @param documentation sections",
332 aName, context.memberDef->qualifiedName());
333 }
334 }
335 }
336 if (!undocParams.empty() && Config_getBool(WARN_IF_INCOMPLETE_DOC))
337 {
338 bool first=TRUE;
339 QCString errMsg = "The following parameter";
340 if (undocParams.size()>1) errMsg+="s";
341 errMsg+=" of "+
342 QCString(context.memberDef->qualifiedName()) +
343 QCString(argListToString(al)) +
344 (undocParams.size()>1 ? " are" : " is") + " not documented:\n";
345 for (const Argument &a : undocParams)
346 {
347 QCString argName = context.memberDef->isDefine() ? a.type : a.name;
348 if (lang==SrcLangExt::Fortran) argName = argName.lower();
349 argName=argName.stripWhiteSpace();
350 if (!first) errMsg+="\n";
351 first=FALSE;
352 errMsg+=" parameter '"+argName+"'";
353 }
354 warn_incomplete_doc(context.memberDef->docFile(), context.memberDef->docLine(), "{}", errMsg);
355 }
356 }
357 else
358 {
359 if (context.paramsFound.empty() && Config_getBool(WARN_IF_DOC_ERROR))
360 {
361 warn_doc_error(context.memberDef->docFile(),
362 context.memberDef->docLine(),
363 "{} has @param documentation sections but no arguments",
364 context.memberDef->qualifiedName());
365 }
366 }
367 }
368}
size_t size() const
Definition arguments.h:100
void push_back(const Argument &a)
Definition arguments.h:102
#define warn_incomplete_doc(file, line, fmt,...)
Definition message.h:107

References argListToString(), Config_getBool, context, ArgumentList::empty(), QCString::endsWith(), FALSE, QCString::isEmpty(), QCString::left(), QCString::length(), QCString::lower(), ArgumentList::push_back(), ArgumentList::size(), QCString::str(), QCString::stripWhiteSpace(), TRUE, warn_doc_error, and warn_incomplete_doc.

Referenced by validatingParseDoc().

◆ defaultHandleTitleAndSize()

void DocParser::defaultHandleTitleAndSize ( const CommandType cmd,
DocNodeVariant * parent,
DocNodeList & children,
QCString & width,
QCString & height )

Definition at line 1012 of file docparser.cpp.

1013{
1014 AUTO_TRACE();
1015 auto ns = AutoNodeStack(this,parent);
1016
1017 // parse title
1018 tokenizer.setStateTitle();
1019 Token tok = tokenizer.lex();
1020 while (!tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1021 {
1022 if (tok.is(TokenRetval::TK_WORD) && (context.token->name=="width=" || context.token->name=="height="))
1023 {
1024 // special case: no title, but we do have a size indicator
1025 break;
1026 }
1027 else if (tok.is(TokenRetval::TK_HTMLTAG))
1028 {
1029 tokenizer.unputString(context.token->text);
1030 break;
1031 }
1032 if (!defaultHandleToken(parent,tok,children))
1033 {
1034 errorHandleDefaultToken(parent,tok,children,Mappers::cmdMapper->find(cmd));
1035 }
1036 tok = tokenizer.lex();
1037 }
1038 // parse size attributes
1039 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1040 {
1041 tok=tokenizer.lex();
1042 }
1043 while (tok.is_any_of(TokenRetval::TK_WHITESPACE,TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG)) // there are values following the title
1044 {
1045 if (tok.is(TokenRetval::TK_WORD))
1046 {
1047 if (context.token->name=="width=" || context.token->name=="height=")
1048 {
1049 tokenizer.setStateTitleAttrValue();
1050 context.token->name = context.token->name.left(context.token->name.length()-1);
1051 }
1052
1053 if (context.token->name=="width")
1054 {
1055 width = context.token->chars;
1056 }
1057 else if (context.token->name=="height")
1058 {
1059 height = context.token->chars;
1060 }
1061 else // other text after the title -> treat as normal text
1062 {
1063 tokenizer.unputString(context.token->name);
1064 //warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unknown option '{}' after \\{} command, expected 'width' or 'height'",
1065 // context.token->name, Mappers::cmdMapper->find(cmd));
1066 break;
1067 }
1068 }
1069
1070 tok=tokenizer.lex();
1071 // if we found something we did not expect, push it back to the stream
1072 // so it can still be processed
1073 if (tok.is_any_of(TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS))
1074 {
1075 tokenizer.unputString(context.token->name);
1076 tokenizer.unputString(tok.is(TokenRetval::TK_COMMAND_AT) ? "@" : "\\");
1077 break;
1078 }
1079 else if (tok.is(TokenRetval::TK_SYMBOL))
1080 {
1081 tokenizer.unputString(context.token->name);
1082 break;
1083 }
1084 else if (tok.is(TokenRetval::TK_HTMLTAG))
1085 {
1086 tokenizer.unputString(context.token->text);
1087 break;
1088 }
1089 }
1090 tokenizer.setStatePara();
1091
1093 AUTO_TRACE_EXIT("width={} height={}",width,height);
1094}
bool defaultHandleToken(DocNodeVariant *parent, Token tok, DocNodeList &children, bool handleWord=TRUE)
DocTokenizer tokenizer
void handlePendingStyleCommands(DocNodeVariant *parent, DocNodeList &children)
void errorHandleDefaultToken(DocNodeVariant *parent, Token tok, DocNodeList &children, const QCString &txt)
bool is(TokenRetval rv) const
bool is_any_of(ARGS... args) const
#define AUTO_TRACE(...)
Definition docnode.cpp:46
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:48
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1330
const Mapper< CommandType > * cmdMapper

References AUTO_TRACE, AUTO_TRACE_EXIT, Mappers::cmdMapper, context, defaultHandleToken(), errorHandleDefaultToken(), handlePendingStyleCommands(), Token::is(), Token::is_any_of(), parent(), and tokenizer.

Referenced by DocPara::handleCommand(), DocDiaFile::parse(), DocDotFile::parse(), DocImage::parse(), DocMscFile::parse(), and DocPlantUmlFile::parse().

◆ defaultHandleToken()

bool DocParser::defaultHandleToken ( DocNodeVariant * parent,
Token tok,
DocNodeList & children,
bool handleWord = TRUE )

Definition at line 1214 of file docparser.cpp.

1215{
1216 AUTO_TRACE("token={} handleWord={}",tok.to_string(),handleWord);
1217 if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD,TokenRetval::TK_SYMBOL,TokenRetval::TK_URL,
1218 TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS,TokenRetval::TK_HTMLTAG)
1219 )
1220 {
1221 }
1222reparsetoken:
1223 QCString tokenName = context.token->name;
1224 AUTO_TRACE_ADD("tokenName={}",tokenName);
1225 switch (tok.value())
1226 {
1227 case TokenRetval::TK_COMMAND_AT:
1228 // fall through
1229 case TokenRetval::TK_COMMAND_BS:
1230 switch (Mappers::cmdMapper->map(tokenName))
1231 {
1233 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_BSlash);
1234 break;
1236 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_At);
1237 break;
1239 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Less);
1240 break;
1242 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Greater);
1243 break;
1245 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Amp);
1246 break;
1248 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dollar);
1249 break;
1251 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Hash);
1252 break;
1254 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_DoubleColon);
1255 break;
1257 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Percent);
1258 break;
1260 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1261 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1262 break;
1264 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1265 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1266 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1267 break;
1269 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quot);
1270 break;
1272 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dot);
1273 break;
1275 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Exclam);
1276 break;
1278 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quest);
1279 break;
1281 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Plus);
1282 break;
1284 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1285 break;
1287 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Equal);
1288 break;
1290 {
1291 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,TRUE);
1292 tok=handleStyleArgument(parent,children,tokenName);
1293 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,FALSE);
1294 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1295 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1296 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1297 {
1298 AUTO_TRACE_ADD("CommandType::CMD_EMPHASIS: reparsing");
1299 goto reparsetoken;
1300 }
1301 }
1302 break;
1304 {
1305 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,TRUE);
1306 tok=handleStyleArgument(parent,children,tokenName);
1307 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,FALSE);
1308 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1309 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1310 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1311 {
1312 AUTO_TRACE_ADD("CommandType::CMD_BOLD: reparsing");
1313 goto reparsetoken;
1314 }
1315 }
1316 break;
1318 {
1319 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,TRUE);
1320 tok=handleStyleArgument(parent,children,tokenName);
1321 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,FALSE);
1322 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1323 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1324 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1325 {
1326 AUTO_TRACE_ADD("CommandType::CMD_CODE: reparsing");
1327 goto reparsetoken;
1328 }
1329 }
1330 break;
1332 {
1333 tokenizer.setStateHtmlOnly();
1334 tok = tokenizer.lex();
1335 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::HtmlOnly,context.isExample,context.exampleName,context.token->name=="block");
1336 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1337 {
1338 warn_doc_error(context.fileName,tokenizer.getLineNr(),"htmlonly section ended without end marker");
1339 }
1340 tokenizer.setStatePara();
1341 }
1342 break;
1344 {
1345 tokenizer.setStateManOnly();
1346 tok = tokenizer.lex();
1347 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::ManOnly,context.isExample,context.exampleName);
1348 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1349 {
1350 warn_doc_error(context.fileName,tokenizer.getLineNr(),"manonly section ended without end marker");
1351 }
1352 tokenizer.setStatePara();
1353 }
1354 break;
1356 {
1357 tokenizer.setStateRtfOnly();
1358 tok = tokenizer.lex();
1359 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::RtfOnly,context.isExample,context.exampleName);
1360 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1361 {
1362 warn_doc_error(context.fileName,tokenizer.getLineNr(),"rtfonly section ended without end marker");
1363 }
1364 tokenizer.setStatePara();
1365 }
1366 break;
1368 {
1369 tokenizer.setStateLatexOnly();
1370 tok = tokenizer.lex();
1371 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::LatexOnly,context.isExample,context.exampleName);
1372 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1373 {
1374 warn_doc_error(context.fileName,tokenizer.getLineNr(),"latexonly section ended without end marker");
1375 }
1376 tokenizer.setStatePara();
1377 }
1378 break;
1380 {
1381 tokenizer.setStateXmlOnly();
1382 tok = tokenizer.lex();
1383 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::XmlOnly,context.isExample,context.exampleName);
1384 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1385 {
1386 warn_doc_error(context.fileName,tokenizer.getLineNr(),"xmlonly section ended without end marker");
1387 }
1388 tokenizer.setStatePara();
1389 }
1390 break;
1392 {
1393 tokenizer.setStateDbOnly();
1394 tok = tokenizer.lex();
1395 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::DocbookOnly,context.isExample,context.exampleName);
1396 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1397 {
1398 warn_doc_error(context.fileName,tokenizer.getLineNr(),"docbookonly section ended without end marker");
1399 }
1400 tokenizer.setStatePara();
1401 }
1402 break;
1404 {
1405 children.append<DocFormula>(this,parent,context.token->id);
1406 }
1407 break;
1410 {
1411 handleAnchor(parent,children);
1412 }
1413 break;
1415 {
1416 handlePrefix(parent,children);
1417 }
1418 break;
1420 {
1421 handleInternalRef(parent,children);
1422 tokenizer.setStatePara();
1423 }
1424 break;
1426 {
1427 tokenizer.setStateSetScope();
1428 (void)tokenizer.lex();
1429 context.context = context.token->name;
1430 //printf("Found scope='%s'\n",qPrint(context.context));
1431 tokenizer.setStatePara();
1432 }
1433 break;
1435 handleImage(parent,children);
1436 break;
1438 tokenizer.pushState();
1439 tokenizer.setStateILine();
1440 (void)tokenizer.lex();
1441 tokenizer.popState();
1442 break;
1444 tokenizer.pushState();
1445 tokenizer.setStateIFile();
1446 (void)tokenizer.lex();
1447 tokenizer.popState();
1448 break;
1449 default:
1450 return FALSE;
1451 }
1452 break;
1453 case TokenRetval::TK_HTMLTAG:
1454 {
1455 auto handleEnterLeaveStyle = [this,&parent,&children,&tokenName](DocStyleChange::Style style) {
1456 if (!context.token->endTag)
1457 {
1458 handleStyleEnter(parent,children,style,tokenName,&context.token->attribs);
1459 }
1460 else
1461 {
1462 handleStyleLeave(parent,children,style,tokenName);
1463 }
1464 };
1465 switch (Mappers::htmlTagMapper->map(tokenName))
1466 {
1468 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <div> tag in heading");
1469 break;
1471 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <pre> tag in heading");
1472 break;
1474 handleEnterLeaveStyle(DocStyleChange::Span);
1475 break;
1477 handleEnterLeaveStyle(DocStyleChange::Bold);
1478 break;
1480 handleEnterLeaveStyle(DocStyleChange::S);
1481 break;
1483 handleEnterLeaveStyle(DocStyleChange::Strike);
1484 break;
1486 handleEnterLeaveStyle(DocStyleChange::Del);
1487 break;
1489 handleEnterLeaveStyle(DocStyleChange::Underline);
1490 break;
1492 handleEnterLeaveStyle(DocStyleChange::Ins);
1493 break;
1495 case HtmlTagType::XML_C:
1496 handleEnterLeaveStyle(DocStyleChange::Code);
1497 break;
1499 handleEnterLeaveStyle(DocStyleChange::Kbd);
1500 break;
1502 handleEnterLeaveStyle(DocStyleChange::Typewriter);
1503 break;
1505 handleEnterLeaveStyle(DocStyleChange::Italic);
1506 break;
1508 handleEnterLeaveStyle(DocStyleChange::Subscript);
1509 break;
1511 handleEnterLeaveStyle(DocStyleChange::Superscript);
1512 break;
1514 handleEnterLeaveStyle(DocStyleChange::Center);
1515 break;
1517 handleEnterLeaveStyle(DocStyleChange::Small);
1518 break;
1520 handleEnterLeaveStyle(DocStyleChange::Cite);
1521 break;
1523 if (!context.token->endTag)
1524 {
1525 handleImg(parent,children,context.token->attribs);
1526 }
1527 break;
1528 default:
1529 return FALSE;
1530 break;
1531 }
1532 }
1533 break;
1534 case TokenRetval::TK_SYMBOL:
1535 {
1538 {
1539 children.append<DocSymbol>(this,parent,s);
1540 }
1541 else
1542 {
1543 return FALSE;
1544 }
1545 }
1546 break;
1547 case TokenRetval::TK_WHITESPACE:
1548 case TokenRetval::TK_NEWPARA:
1549handlepara:
1550 if (insidePRE(parent) || !children.empty())
1551 {
1552 children.append<DocWhiteSpace>(this,parent,context.token->chars);
1553 }
1554 break;
1555 case TokenRetval::TK_LNKWORD:
1556 if (handleWord)
1557 {
1558 handleLinkedWord(parent,children);
1559 }
1560 else
1561 return FALSE;
1562 break;
1563 case TokenRetval::TK_WORD:
1564 if (handleWord)
1565 {
1566 children.append<DocWord>(this,parent,context.token->name);
1567 }
1568 else
1569 return FALSE;
1570 break;
1571 case TokenRetval::TK_URL:
1572 if (context.insideHtmlLink)
1573 {
1574 children.append<DocWord>(this,parent,context.token->name);
1575 }
1576 else
1577 {
1578 children.append<DocURL>(this,parent,context.token->name,context.token->isEMailAddr);
1579 }
1580 break;
1581 default:
1582 return FALSE;
1583 }
1584 return TRUE;
1585}
void handleLinkedWord(DocNodeVariant *parent, DocNodeList &children, bool ignoreAutoLinkFlag=FALSE)
void handleInternalRef(DocNodeVariant *parent, DocNodeList &children)
void handleStyleLeave(DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName)
void handleImage(DocNodeVariant *parent, DocNodeList &children)
void handleStyleEnter(DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName, const HtmlAttribList *attribs)
void handlePrefix(DocNodeVariant *parent, DocNodeList &children)
Token handleStyleArgument(DocNodeVariant *parent, DocNodeList &children, const QCString &cmdName)
void handleAnchor(DocNodeVariant *parent, DocNodeList &children)
void handleImg(DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
static HtmlEntityMapper::SymType decodeSymbol(const QCString &symName)
Definition docnode.cpp:153
TOKEN_SPECIFICATIONS RETVAL_SPECIFICATIONS const char * to_string() const
TokenRetval value() const
@ CMD_INTERNALREF
Definition cmdmapper.h:65
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:47
bool insidePRE(const DocNodeVariant *n)
const Mapper< HtmlTagType > * htmlTagMapper
void append(Args &&... args)
Append a new DocNodeVariant to the list by constructing it with type T and parameters Args.
Definition docnode.h:1399

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, DocStyleChange::Bold, DocStyleChange::Center, DocStyleChange::Cite, CMD_AMP, CMD_ANCHOR, CMD_AT, CMD_BOLD, CMD_BSLASH, CMD_CODE, CMD_DBONLY, CMD_DCOLON, CMD_DOLLAR, CMD_EMPHASIS, CMD_EQUAL, CMD_EXCLAMATION, CMD_FORMULA, CMD_GREATER, CMD_HASH, CMD_HTMLONLY, CMD_IANCHOR, CMD_IFILE, CMD_ILINE, CMD_IMAGE, CMD_INTERNALREF, CMD_IPREFIX, CMD_LATEXONLY, CMD_LESS, CMD_MANONLY, CMD_MDASH, CMD_MINUS, CMD_NDASH, CMD_PERCENT, CMD_PLUS, CMD_PUNT, CMD_QUESTION, CMD_QUOTE, CMD_RTFONLY, CMD_SETSCOPE, CMD_XMLONLY, Mappers::cmdMapper, DocStyleChange::Code, context, DocSymbol::decodeSymbol(), DocStyleChange::Del, DocVerbatim::DocbookOnly, GrowVector< T >::empty(), FALSE, handleAnchor(), handleImage(), handleImg(), handleInternalRef(), handleLinkedWord(), handlePrefix(), handleStyleArgument(), handleStyleEnter(), handleStyleLeave(), HTML_BOLD, HTML_CENTER, HTML_CITE, HTML_CODE, HTML_DEL, HTML_DIV, HTML_EMPHASIS, HTML_IMG, HTML_INS, HTML_KBD, HTML_PRE, HTML_S, HTML_SMALL, HTML_SPAN, HTML_STRIKE, HTML_SUB, HTML_SUP, HTML_TT, HTML_UNDERLINE, DocVerbatim::HtmlOnly, Mappers::htmlTagMapper, DocStyleChange::Ins, insidePRE(), Token::is(), Token::is_any_of(), DocStyleChange::Italic, DocStyleChange::Kbd, DocVerbatim::LatexOnly, DocVerbatim::ManOnly, parent(), DocVerbatim::RtfOnly, DocStyleChange::S, DocStyleChange::Small, DocStyleChange::Span, DocStyleChange::Strike, DocStyleChange::Subscript, DocStyleChange::Superscript, HtmlEntityMapper::Sym_Amp, HtmlEntityMapper::Sym_At, HtmlEntityMapper::Sym_BSlash, HtmlEntityMapper::Sym_Dollar, HtmlEntityMapper::Sym_Dot, HtmlEntityMapper::Sym_DoubleColon, HtmlEntityMapper::Sym_Equal, HtmlEntityMapper::Sym_Exclam, HtmlEntityMapper::Sym_Greater, HtmlEntityMapper::Sym_Hash, HtmlEntityMapper::Sym_Less, HtmlEntityMapper::Sym_Minus, HtmlEntityMapper::Sym_Percent, HtmlEntityMapper::Sym_Plus, HtmlEntityMapper::Sym_Quest, HtmlEntityMapper::Sym_Quot, HtmlEntityMapper::Sym_Unknown, Token::to_string(), tokenizer, TRUE, DocStyleChange::Typewriter, DocStyleChange::Underline, Token::value(), warn_doc_error, XML_C, and DocVerbatim::XmlOnly.

Referenced by defaultHandleTitleAndSize(), handleStyleArgument(), and DocPara::injectToken().

◆ errorHandleDefaultToken()

void DocParser::errorHandleDefaultToken ( DocNodeVariant * parent,
Token tok,
DocNodeList & children,
const QCString & txt )

Definition at line 536 of file docparser.cpp.

538{
539 switch (tok.value())
540 {
541 case TokenRetval::TK_COMMAND_AT:
542 // fall through
543 case TokenRetval::TK_COMMAND_BS:
544 {
545 char cs[2] = { tok.command_to_char(), 0 };
546 children.append<DocWord>(this,parent,cs + context.token->name);
547 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Illegal command '{:c}{}' found as part of a {}",
548 tok.command_to_char(),context.token->name,txt);
549 }
550 break;
551 case TokenRetval::TK_SYMBOL:
552 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported symbol '{}' found as part of a {}",
553 qPrint(context.token->name), qPrint(txt));
554 break;
555 case TokenRetval::TK_HTMLTAG:
556 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unsupported HTML tag <{}{}> found as part of a {}",
557 context.token->endTag ? "/" : "",context.token->name, txt);
558 break;
559 default:
560 children.append<DocWord>(this,parent,context.token->name);
561 warn_doc_error(context.fileName,tokenizer.getLineNr(),"Unexpected token {} found as part of a {}",
562 tok.to_string(), txt);
563 break;
564 }
565}
char command_to_char() const

References DocNodeList::append(), Token::command_to_char(), context, parent(), qPrint(), Token::to_string(), tokenizer, Token::value(), and warn_doc_error.

Referenced by defaultHandleTitleAndSize(), handleStyleArgument(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlHeader::parse(), DocHtmlSummary::parse(), DocInternalRef::parse(), DocRef::parse(), DocSecRefItem::parse(), DocTitle::parse(), and DocVhdlFlow::parse().

◆ findAndCopyImage()

QCString DocParser::findAndCopyImage ( const QCString & fileName,
DocImage::Type type,
bool doWarn = true )

search for an image in the imageNameDict and if found copies the image to the output directory (which depends on the type parameter).

Definition at line 94 of file docparser.cpp.

95{
96 QCString result;
97 bool ambig = false;
98 FileDef *fd = findFileDef(Doxygen::imageNameLinkedMap,fileName,ambig);
99 //printf("Search for %s\n",fileName);
100 if (fd)
101 {
102 if (ambig & doWarn)
103 {
104 warn_doc_error(context.fileName,tokenizer.getLineNr(),
105 "image file name '{}' is ambiguous.\n"
106 "Possible candidates:\n{}", fileName,showFileDefMatches(Doxygen::imageNameLinkedMap,fileName));
107 }
108
109 QCString inputFile = fd->absFilePath();
110 FileInfo infi(inputFile.str());
111 if (infi.exists())
112 {
113 result = fileName;
114 int i = result.findRev('/');
115 if (i!=-1 || (i=result.findRev('\\'))!=-1)
116 {
117 result = result.right(static_cast<int>(result.length())-i-1);
118 }
119 //printf("fileName=%s result=%s\n",fileName,qPrint(result));
120 QCString outputDir;
121 switch(type)
122 {
123 case DocImage::Html:
124 if (!Config_getBool(GENERATE_HTML)) return result;
125 outputDir = Config_getString(HTML_OUTPUT);
126 break;
127 case DocImage::Latex:
128 if (!Config_getBool(GENERATE_LATEX)) return result;
129 outputDir = Config_getString(LATEX_OUTPUT);
130 break;
132 if (!Config_getBool(GENERATE_DOCBOOK)) return result;
133 outputDir = Config_getString(DOCBOOK_OUTPUT);
134 break;
135 case DocImage::Rtf:
136 if (!Config_getBool(GENERATE_RTF)) return result;
137 outputDir = Config_getString(RTF_OUTPUT);
138 break;
139 case DocImage::Xml:
140 if (!Config_getBool(GENERATE_XML)) return result;
141 outputDir = Config_getString(XML_OUTPUT);
142 break;
143 }
144 QCString outputFile = outputDir+"/"+result;
145 FileInfo outfi(outputFile.str());
146 if (outfi.isSymLink())
147 {
148 Dir().remove(outputFile.str());
149 warn_doc_error(context.fileName,tokenizer.getLineNr(),
150 "destination of image {} is a symlink, replacing with image",
151 outputFile);
152 }
153 if (outputFile!=inputFile) // prevent copying to ourself
154 {
155 if (copyFile(inputFile,outputFile) && type==DocImage::Html)
156 {
158 }
159 }
160 }
161 else
162 {
163 warn_doc_error(context.fileName,tokenizer.getLineNr(),
164 "could not open image {}",fileName);
165 }
166
167 if (type==DocImage::Latex && Config_getBool(USE_PDFLATEX) &&
168 fd->name().endsWith(".eps")
169 )
170 { // we have an .eps image in pdflatex mode => convert it to a pdf.
171 QCString outputDir = Config_getString(LATEX_OUTPUT);
172 QCString baseName = fd->name().left(fd->name().length()-4);
173 QCString epstopdfArgs(4096, QCString::ExplicitSize);
174 epstopdfArgs.sprintf("\"%s/%s.eps\" --outfile=\"%s/%s.pdf\"",
175 qPrint(outputDir), qPrint(baseName),
176 qPrint(outputDir), qPrint(baseName));
177 if (Portable::system("epstopdf",epstopdfArgs)!=0)
178 {
179 err("Problems running epstopdf. Check your TeX installation!\n");
180 }
181 else
182 {
183 Dir().remove(outputDir.str()+"/"+baseName.str()+".eps");
184 }
185 return baseName;
186 }
187 }
188 else
189 {
190 result=fileName;
191 if (!result.startsWith("http:") && !result.startsWith("https:") && doWarn)
192 {
193 warn_doc_error(context.fileName,tokenizer.getLineNr(),
194 "image file {} is not found in IMAGE_PATH: "
195 "assuming external image.",fileName
196 );
197 }
198 }
199 return result;
200}
@ DocBook
Definition docnode.h:644
static FileNameLinkedMap * imageNameLinkedMap
Definition doxygen.h:106
static IndexList * indexList
Definition doxygen.h:134
virtual QCString absFilePath() const =0
void addImageFile(const QCString &name)
Definition indexlist.h:127
QCString right(size_t len) const
Definition qcstring.h:219
@ ExplicitSize
Definition qcstring.h:133
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
#define Config_getString(name)
Definition config.h:32
#define err(fmt,...)
Definition message.h:127
int system(const QCString &command, const QCString &args, bool commandHasConsole=true)
Definition portable.cpp:106
QCString showFileDefMatches(const FileNameLinkedMap *fnMap, const QCString &n)
Definition util.cpp:3545
bool copyFile(const QCString &src, const QCString &dest)
Copies the contents of file with name src to the newly created file with name dest.
Definition util.cpp:6376
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:3417

References FileDef::absFilePath(), Config_getBool, Config_getString, context, copyFile(), DocImage::DocBook, QCString::endsWith(), err, FileInfo::exists(), QCString::ExplicitSize, findFileDef(), QCString::findRev(), DocImage::Html, Doxygen::imageNameLinkedMap, Doxygen::indexList, FileInfo::isSymLink(), DocImage::Latex, QCString::left(), QCString::length(), Definition::name(), qPrint(), Dir::remove(), QCString::right(), DocImage::Rtf, showFileDefMatches(), QCString::sprintf(), QCString::startsWith(), QCString::str(), Portable::system(), tokenizer, warn_doc_error, and DocImage::Xml.

Referenced by handleImage(), and handleImg().

◆ findDocsForMemberOrCompound()

bool DocParser::findDocsForMemberOrCompound ( const QCString & commandName,
QCString * pDoc,
QCString * pBrief,
const Definition ** pDef )

Looks for a documentation block with name commandName in the current context (g_parserContext.context). The resulting documentation string is put in pDoc, the definition in which the documentation was found is put in pDef.

Return values
TRUEif name was found.
FALSEif name was not found.

Definition at line 383 of file docparser.cpp.

387{
388 AUTO_TRACE("commandName={}",commandName);
389 *pDoc="";
390 *pBrief="";
391 *pDef=nullptr;
392 QCString cmdArg=commandName;
393 if (cmdArg.isEmpty())
394 {
395 AUTO_TRACE_EXIT("empty");
396 return false;
397 }
398
399 const FileDef *fd=nullptr;
400 const GroupDef *gd=nullptr;
401 const PageDef *pd=nullptr;
402 gd = Doxygen::groupLinkedMap->find(cmdArg);
403 if (gd) // group
404 {
405 *pDoc=gd->documentation();
406 *pBrief=gd->briefDescription();
407 *pDef=gd;
408 AUTO_TRACE_EXIT("group");
409 return true;
410 }
411 pd = Doxygen::pageLinkedMap->find(cmdArg);
412 if (pd) // page
413 {
414 *pDoc=pd->documentation();
415 *pBrief=pd->briefDescription();
416 *pDef=pd;
417 AUTO_TRACE_EXIT("page");
418 return true;
419 }
420 bool ambig = false;
421 fd = findFileDef(Doxygen::inputNameLinkedMap,cmdArg,ambig);
422 if (fd && !ambig) // file
423 {
424 *pDoc=fd->documentation();
425 *pBrief=fd->briefDescription();
426 *pDef=fd;
427 AUTO_TRACE_EXIT("file");
428 return true;
429 }
430
431 // for symbols we need to normalize the separator, so A#B, or A\B, or A.B becomes A::B
432 cmdArg = substitute(cmdArg,"#","::");
433 cmdArg = substitute(cmdArg,"\\","::");
434 bool extractAnonNs = Config_getBool(EXTRACT_ANON_NSPACES);
435 if (extractAnonNs &&
436 cmdArg.startsWith("anonymous_namespace{")
437 )
438 {
439 size_t rightBracePos = cmdArg.find("}", static_cast<int>(qstrlen("anonymous_namespace{")));
440 QCString leftPart = cmdArg.left(rightBracePos + 1);
441 QCString rightPart = cmdArg.right(cmdArg.size() - rightBracePos - 1);
442 rightPart = substitute(rightPart, ".", "::");
443 cmdArg = leftPart + rightPart;
444 }
445 else
446 {
447 cmdArg = substitute(cmdArg,".","::");
448 }
449
450 int l=static_cast<int>(cmdArg.length());
451
452 int funcStart=cmdArg.find('(');
453 if (funcStart==-1)
454 {
455 funcStart=l;
456 }
457 else
458 {
459 // Check for the case of operator() and the like.
460 // beware of scenarios like operator()((foo)bar)
461 int secondParen = cmdArg.find('(', funcStart+1);
462 int leftParen = cmdArg.find(')', funcStart+1);
463 if (leftParen!=-1 && secondParen!=-1)
464 {
465 if (leftParen<secondParen)
466 {
467 funcStart=secondParen;
468 }
469 }
470 }
471
472 QCString name=removeRedundantWhiteSpace(cmdArg.left(funcStart));
473 QCString args=cmdArg.right(l-funcStart);
474 // try if the link is to a member
475 GetDefInput input(
476 context.context.find('.')==-1 ? context.context : QCString(), // find('.') is a hack to detect files
477 name,
478 args);
479 input.checkCV=true;
480 GetDefResult result = getDefs(input);
481 //printf("found=%d context=%s name=%s\n",result.found,qPrint(context.context),qPrint(name));
482 if (result.found && result.md)
483 {
484 *pDoc=result.md->documentation();
485 *pBrief=result.md->briefDescription();
486 *pDef=result.md;
487 AUTO_TRACE_EXIT("member");
488 return true;
489 }
490
491 int scopeOffset=static_cast<int>(context.context.length());
492 do // for each scope
493 {
494 QCString fullName=cmdArg;
495 if (scopeOffset>0)
496 {
497 fullName.prepend(context.context.left(scopeOffset)+"::");
498 }
499 //printf("Trying fullName='%s'\n",qPrint(fullName));
500
501 // try class, namespace, group, page, file reference
502 const ClassDef *cd = Doxygen::classLinkedMap->find(fullName);
503 if (cd) // class
504 {
505 *pDoc=cd->documentation();
506 *pBrief=cd->briefDescription();
507 *pDef=cd;
508 AUTO_TRACE_EXIT("class");
509 return true;
510 }
511 const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(fullName);
512 if (nd) // namespace
513 {
514 *pDoc=nd->documentation();
515 *pBrief=nd->briefDescription();
516 *pDef=nd;
517 AUTO_TRACE_EXIT("namespace");
518 return true;
519 }
520 if (scopeOffset==0)
521 {
522 scopeOffset=-1;
523 }
524 else
525 {
526 scopeOffset = context.context.findRev("::",scopeOffset-1);
527 if (scopeOffset==-1) scopeOffset=0;
528 }
529 } while (scopeOffset>=0);
530
531 AUTO_TRACE_EXIT("not found");
532 return FALSE;
533}
virtual QCString briefDescription(bool abbreviate=FALSE) const =0
virtual QCString documentation() const =0
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:115
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:105
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:96
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:100
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:114
const T * find(const std::string &key) const
Definition linkedmap.h:47
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:407
bool startsWith(const char *s) const
Definition qcstring.h:492
size_t size() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:156
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:477
uint32_t qstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition qcstring.h:58
const MemberDef * md
Definition util.h:125
bool found
Definition util.h:124
QCString removeRedundantWhiteSpace(const QCString &s)
Definition util.cpp:579
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:2823

References AUTO_TRACE, AUTO_TRACE_EXIT, Definition::briefDescription(), GetDefInput::checkCV, Doxygen::classLinkedMap, Config_getBool, context, Definition::documentation(), FALSE, QCString::find(), findFileDef(), GetDefResult::found, getDefs(), Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, QCString::isEmpty(), QCString::left(), QCString::length(), GetDefResult::md, Doxygen::namespaceLinkedMap, Doxygen::pageLinkedMap, QCString::prepend(), qstrlen(), removeRedundantWhiteSpace(), QCString::right(), QCString::size(), QCString::startsWith(), and substitute().

Referenced by processCopyDoc().

◆ handleAHref()

Token DocParser::handleAHref ( DocNodeVariant * parent,
DocNodeList & children,
const HtmlAttribList & tagHtmlAttribs )

Definition at line 713 of file docparser.cpp.

715{
716 AUTO_TRACE();
717 size_t index=0;
718 Token retval = Token::make_RetVal_OK();
719 for (const auto &opt : tagHtmlAttribs)
720 {
721 if (opt.name=="name" || opt.name=="id") // <a name=label> or <a id=label> tag
722 {
723 if (!opt.value.isEmpty())
724 {
725 children.append<DocAnchor>(this,parent,opt.value,TRUE);
726 break; // stop looking for other tag attribs
727 }
728 else
729 {
730 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <a> tag with name option but without value!");
731 }
732 }
733 else if (opt.name=="href") // <a href=url>..</a> tag
734 {
735 // copy attributes
736 HtmlAttribList attrList = tagHtmlAttribs;
737 // and remove the href attribute
738 attrList.erase(attrList.begin()+index);
739 QCString relPath;
740 if (opt.value.at(0) != '#') relPath = context.relPath;
741 children.append<DocHRef>(this, parent, attrList,
742 opt.value, relPath,
743 convertNameToFile(context.fileName, FALSE, TRUE));
744 context.insideHtmlLink=TRUE;
745 retval = children.get_last<DocHRef>()->parse();
746 context.insideHtmlLink=FALSE;
747 tokenizer.setStatePara();
748 break;
749 }
750 else // unsupported option for tag a
751 {
752 }
753 ++index;
754 }
755 return retval;
756}
bool parse(const QCString &fileName, bool update=FALSE, CompareMode compareMode=CompareMode::Full)
T * get_last()
Returns a pointer to the last element in the list if that element exists and holds a T,...
Definition docnode.h:1410
QCString convertNameToFile(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:4020

References DocNodeList::append(), AUTO_TRACE, context, convertNameToFile(), FALSE, DocNodeList::get_last(), parent(), tokenizer, TRUE, and warn_doc_error.

Referenced by DocPara::handleHtmlStartTag(), DocHtmlDescTitle::parse(), and DocHtmlHeader::parse().

◆ handleAnchor()

void DocParser::handleAnchor ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 948 of file docparser.cpp.

949{
950 AUTO_TRACE();
951 Token tok=tokenizer.lex();
952 if (!tok.is(TokenRetval::TK_WHITESPACE))
953 {
954 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
955 context.token->name);
956 return;
957 }
958 tokenizer.setStateAnchor();
959 tok=tokenizer.lex();
960 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
961 {
962 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
963 "argument of command {}",context.token->name);
964 return;
965 }
966 else if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
967 {
968 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
969 tok.to_string(),context.token->name);
970 return;
971 }
972 tokenizer.setStatePara();
973 children.append<DocAnchor>(this,parent,context.token->name,FALSE);
974}

References DocNodeList::append(), AUTO_TRACE, context, FALSE, Token::is(), Token::is_any_of(), parent(), Token::to_string(), tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleImage()

void DocParser::handleImage ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 1096 of file docparser.cpp.

1097{
1098 AUTO_TRACE();
1099 bool inlineImage = false;
1100 QCString anchorStr;
1101
1102 Token tok=tokenizer.lex();
1103 if (!tok.is(TokenRetval::TK_WHITESPACE))
1104 {
1105 if (tok.is(TokenRetval::TK_WORD))
1106 {
1107 if (context.token->name == "{")
1108 {
1109 tokenizer.setStateOptions();
1110 tokenizer.lex();
1111 tokenizer.setStatePara();
1112 StringVector optList=split(context.token->name.str(),",");
1113 for (const auto &opt : optList)
1114 {
1115 if (opt.empty()) continue;
1116 QCString locOpt(opt);
1117 QCString locOptLow;
1118 locOpt = locOpt.stripWhiteSpace();
1119 locOptLow = locOpt.lower();
1120 if (locOptLow == "inline")
1121 {
1122 inlineImage = true;
1123 }
1124 else if (locOptLow.startsWith("anchor:"))
1125 {
1126 if (!anchorStr.isEmpty())
1127 {
1128 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1129 "multiple use of option 'anchor' for 'image' command, ignoring: '{}'",
1130 locOpt.mid(7));
1131 }
1132 else
1133 {
1134 anchorStr = locOpt.mid(7);
1135 }
1136 }
1137 else
1138 {
1139 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1140 "unknown option '{}' for 'image' command specified",
1141 locOpt);
1142 }
1143 }
1144 tok=tokenizer.lex();
1145 if (!tok.is(TokenRetval::TK_WHITESPACE))
1146 {
1147 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1148 return;
1149 }
1150 }
1151 }
1152 else
1153 {
1154 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1155 return;
1156 }
1157 }
1158 tok=tokenizer.lex();
1159 if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
1160 {
1161 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of \\image",
1162 tok.to_string());
1163 return;
1164 }
1165 tok=tokenizer.lex();
1166 if (!tok.is(TokenRetval::TK_WHITESPACE))
1167 {
1168 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\image command");
1169 return;
1170 }
1172 QCString imgType = context.token->name.lower();
1173 if (imgType=="html") t=DocImage::Html;
1174 else if (imgType=="latex") t=DocImage::Latex;
1175 else if (imgType=="docbook") t=DocImage::DocBook;
1176 else if (imgType=="rtf") t=DocImage::Rtf;
1177 else if (imgType=="xml") t=DocImage::Xml;
1178 else
1179 {
1180 warn_doc_error(context.fileName,tokenizer.getLineNr(),"output format `{}` specified as the first argument of "
1181 "\\image command is not valid", imgType);
1182 return;
1183 }
1184 tokenizer.setStateFile();
1185 tok=tokenizer.lex();
1186 tokenizer.setStatePara();
1187 if (!tok.is(TokenRetval::TK_WORD))
1188 {
1189 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of \\image", tok.to_string());
1190 return;
1191 }
1192 if (!anchorStr.isEmpty())
1193 {
1194 children.append<DocAnchor>(this,parent,anchorStr,true);
1195 }
1196 HtmlAttribList attrList;
1197 children.append<DocImage>(this,parent,attrList,
1198 findAndCopyImage(context.token->name,t),t,"",inlineImage);
1199 children.get_last<DocImage>()->parse();
1200}
QCString findAndCopyImage(const QCString &fileName, DocImage::Type type, bool doWarn=true)
Definition docparser.cpp:94
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
std::vector< std::string > StringVector
Definition containers.h:33
StringVector split(const std::string &s, const std::string &delimiter)
split input string s by string delimiter delimiter.
Definition util.cpp:7135

References DocNodeList::append(), AUTO_TRACE, context, DocImage::DocBook, findAndCopyImage(), DocNodeList::get_last(), DocImage::Html, Token::is(), Token::is_any_of(), QCString::isEmpty(), DocImage::Latex, QCString::lower(), QCString::mid(), parent(), DocImage::Rtf, split(), QCString::startsWith(), QCString::stripWhiteSpace(), Token::to_string(), tokenizer, warn_doc_error, and DocImage::Xml.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleImg()

void DocParser::handleImg ( DocNodeVariant * parent,
DocNodeList & children,
const HtmlAttribList & tagHtmlAttribs )

Definition at line 1589 of file docparser.cpp.

1590{
1591 AUTO_TRACE();
1592 bool found=FALSE;
1593 size_t index=0;
1594 for (const auto &opt : tagHtmlAttribs)
1595 {
1596 AUTO_TRACE_ADD("option name={} value='{}'",opt.name,opt.value);
1597 if (opt.name=="src" && !opt.value.isEmpty())
1598 {
1599 // copy attributes
1600 HtmlAttribList attrList = tagHtmlAttribs;
1601 // and remove the src attribute
1602 attrList.erase(attrList.begin()+index);
1604 children.append<DocImage>(
1605 this,parent,attrList,
1606 findAndCopyImage(opt.value,t,false),
1607 t,opt.value);
1608 found = TRUE;
1609 }
1610 ++index;
1611 }
1612 if (!found)
1613 {
1614 warn_doc_error(context.fileName,tokenizer.getLineNr(),"IMG tag does not have a SRC attribute!");
1615 }
1616}

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, context, FALSE, findAndCopyImage(), DocImage::Html, parent(), tokenizer, TRUE, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleHtmlStartTag().

◆ handleInitialStyleCommands()

void DocParser::handleInitialStyleCommands ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 702 of file docparser.cpp.

703{
704 AUTO_TRACE();
705 while (!context.initialStyleStack.empty())
706 {
707 const DocStyleChange &sc = std::get<DocStyleChange>(*context.initialStyleStack.top());
708 handleStyleEnter(parent,children,sc.style(),sc.tagName(),&sc.attribs());
709 context.initialStyleStack.pop();
710 }
711}
const HtmlAttribList & attribs() const
Definition docnode.h:311
QCString tagName() const
Definition docnode.h:312
Style style() const
Definition docnode.h:307

References DocStyleChange::attribs(), AUTO_TRACE, context, handleStyleEnter(), parent(), DocStyleChange::style(), and DocStyleChange::tagName().

Referenced by DocPara::parse().

◆ handleInternalRef()

void DocParser::handleInternalRef ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 926 of file docparser.cpp.

927{
928 Token tok=tokenizer.lex();
929 QCString tokenName = context.token->name;
930 AUTO_TRACE("name={}",tokenName);
931 if (!tok.is(TokenRetval::TK_WHITESPACE))
932 {
933 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command", tokenName);
934 return;
935 }
936 tokenizer.setStateInternalRef();
937 tok=tokenizer.lex(); // get the reference id
938 if (!tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD))
939 {
940 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
941 tok.to_string(),tokenName);
942 return;
943 }
944 children.append<DocInternalRef>(this,parent,context.token->name);
945 children.get_last<DocInternalRef>()->parse();
946}

References DocNodeList::append(), AUTO_TRACE, context, DocNodeList::get_last(), Token::is(), Token::is_any_of(), parent(), Token::to_string(), tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleLinkedWord()

void DocParser::handleLinkedWord ( DocNodeVariant * parent,
DocNodeList & children,
bool ignoreAutoLinkFlag = FALSE )

Definition at line 782 of file docparser.cpp.

783{
784 // helper to check if word w starts with any of the words in AUTOLINK_IGNORE_WORDS
785 auto ignoreWord = [](const QCString &w) -> bool {
786 const auto &list = Config_getList(AUTOLINK_IGNORE_WORDS);
787 return std::find_if(list.begin(), list.end(),
788 [&w](const auto &ignore) { return w.startsWith(ignore); }
789 )!=list.end();
790 };
791 QCString name = linkToText(context.lang,context.token->name,TRUE);
792 AUTO_TRACE("word={}",name);
793 if ((!context.autolinkSupport && !ignoreAutoLinkFlag) || ignoreWord(context.token->name)) // no autolinking -> add as normal word
794 {
795 children.append<DocWord>(this,parent,name);
796 return;
797 }
798
799 // ------- try to turn the word 'name' into a link
800
801 const Definition *compound=nullptr;
802 const MemberDef *member=nullptr;
803 size_t len = context.token->name.length();
804 ClassDef *cd=nullptr;
805 bool ambig = false;
806 FileDef *fd = findFileDef(Doxygen::inputNameLinkedMap,context.fileName,ambig);
807 auto lang = context.lang;
808 bool inSeeBlock = context.inSeeBlock || context.inCodeStyle;
809 //printf("handleLinkedWord(%s) context.context=%s\n",qPrint(context.token->name),qPrint(context.context));
810 if (!context.insideHtmlLink &&
811 (resolveRef(context.context,context.token->name,inSeeBlock,&compound,&member,lang,TRUE,fd,TRUE)
812 || (!context.context.isEmpty() && // also try with global scope
813 resolveRef(QCString(),context.token->name,inSeeBlock,&compound,&member,lang,FALSE,nullptr,TRUE))
814 )
815 )
816 {
817 //printf("ADD %s = %p (linkable?=%d)\n",qPrint(context.token->name),(void*)member,member ? member->isLinkable() : FALSE);
818 if (member && member->isLinkable()) // member link
819 {
820 AUTO_TRACE_ADD("resolved reference as member link");
821 if (member->isObjCMethod())
822 {
823 bool localLink = context.memberDef ? member->getClassDef()==context.memberDef->getClassDef() : FALSE;
824 name = member->objCMethodName(localLink,inSeeBlock);
825 }
826 children.append<DocLinkedWord>(
827 this,parent,name,
828 member->getReference(),
829 member->getOutputFileBase(),
830 member->anchor(),
831 member->briefDescriptionAsTooltip());
832 }
833 else if (compound->isLinkable()) // compound link
834 {
835 AUTO_TRACE_ADD("resolved reference as compound link");
836 QCString anchor = compound->anchor();
837 if (compound->definitionType()==Definition::TypeFile)
838 {
839 name=context.token->name;
840 }
841 else if (compound->definitionType()==Definition::TypeGroup)
842 {
843 name=toGroupDef(compound)->groupTitle();
844 }
845 children.append<DocLinkedWord>(
846 this,parent,name,
847 compound->getReference(),
848 compound->getOutputFileBase(),
849 anchor,
850 compound->briefDescriptionAsTooltip());
851 }
852 else if (compound->definitionType()==Definition::TypeFile &&
853 (toFileDef(compound))->generateSourceFile()
854 ) // undocumented file that has source code we can link to
855 {
856 AUTO_TRACE_ADD("resolved reference as source link");
857 children.append<DocLinkedWord>(
858 this,parent,context.token->name,
859 compound->getReference(),
860 compound->getSourceFileBase(),
861 "",
862 compound->briefDescriptionAsTooltip());
863 }
864 else // not linkable
865 {
866 AUTO_TRACE_ADD("resolved reference as unlinkable compound={} (linkable={}) member={} (linkable={})",
867 compound ? compound->name() : "<none>", compound ? (int)compound->isLinkable() : -1,
868 member ? member->name() : "<none>", member ? (int)member->isLinkable() : -1);
869 children.append<DocWord>(this,parent,name);
870 }
871 }
872 else if (!context.insideHtmlLink && len>1 && context.token->name.at(len-1)==':')
873 {
874 // special case, where matching Foo: fails to be an Obj-C reference,
875 // but Foo itself might be linkable.
876 context.token->name=context.token->name.left(len-1);
877 handleLinkedWord(parent,children,ignoreAutoLinkFlag);
878 children.append<DocWord>(this,parent,":");
879 }
880 else if (!context.insideHtmlLink && (cd=getClass(context.token->name+"-p")))
881 {
882 // special case 2, where the token name is not a class, but could
883 // be a Obj-C protocol
884 children.append<DocLinkedWord>(
885 this,parent,name,
886 cd->getReference(),
887 cd->getOutputFileBase(),
888 cd->anchor(),
890 }
891 else // normal non-linkable word
892 {
893 AUTO_TRACE_ADD("non-linkable");
894 if (context.token->name.startsWith("#"))
895 {
896 warn_doc_error(context.fileName,tokenizer.getLineNr(),"explicit link request to '{}' could not be resolved",name);
897 }
898 children.append<DocWord>(this,parent,context.token->name);
899 }
900}
virtual bool isLinkable() const =0
virtual DefType definitionType() const =0
virtual QCString anchor() const =0
virtual QCString briefDescriptionAsTooltip() const =0
virtual QCString getReference() const =0
virtual QCString getSourceFileBase() const =0
virtual QCString getOutputFileBase() const =0
virtual QCString groupTitle() const =0
virtual bool isObjCMethod() const =0
virtual const ClassDef * getClassDef() const =0
virtual QCString objCMethodName(bool localLink, bool showStatic) const =0
ClassDef * getClass(const QCString &n)
#define Config_getList(name)
Definition config.h:38
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:1939
GroupDef * toGroupDef(Definition *d)
QCString linkToText(SrcLangExt lang, const QCString &link, bool isFileName)
Definition util.cpp:3221
bool resolveRef(const QCString &scName, const QCString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
Definition util.cpp:2965

References Definition::anchor(), DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, Definition::briefDescriptionAsTooltip(), Config_getList, context, Definition::definitionType(), FALSE, findFileDef(), getClass(), MemberDef::getClassDef(), Definition::getOutputFileBase(), Definition::getReference(), Definition::getSourceFileBase(), GroupDef::groupTitle(), handleLinkedWord(), Doxygen::inputNameLinkedMap, Definition::isLinkable(), MemberDef::isObjCMethod(), linkToText(), Definition::name(), MemberDef::objCMethodName(), parent(), resolveRef(), toFileDef(), toGroupDef(), tokenizer, TRUE, Definition::TypeFile, Definition::TypeGroup, and warn_doc_error.

Referenced by defaultHandleToken(), DocPara::handleHtmlStartTag(), handleLinkedWord(), handleParameterType(), DocPara::parse(), DocParamList::parse(), and DocParamList::parseXml().

◆ handleParameterType()

void DocParser::handleParameterType ( DocNodeVariant * parent,
DocNodeList & children,
const QCString & paramTypes )

Definition at line 902 of file docparser.cpp.

903{
904 QCString name = context.token->name; // save token name
905 AUTO_TRACE("name={}",name);
906 QCString name1;
907 int p=0, i=0, ii=0;
908 while ((i=paramTypes.find('|',p))!=-1)
909 {
910 name1 = paramTypes.mid(p,i-p);
911 ii=name1.find('[');
912 context.token->name=ii!=-1 ? name1.mid(0,ii) : name1; // take part without []
913 handleLinkedWord(parent,children);
914 if (ii!=-1) children.append<DocWord>(this,parent,name1.mid(ii)); // add [] part
915 p=i+1;
916 children.append<DocSeparator>(this,parent,"|");
917 }
918 name1 = paramTypes.mid(p);
919 ii=name1.find('[');
920 context.token->name=ii!=-1 ? name1.mid(0,ii) : name1;
921 handleLinkedWord(parent,children);
922 if (ii!=-1) children.append<DocWord>(this,parent,name1.mid(ii));
923 context.token->name = name; // restore original token name
924}

References DocNodeList::append(), AUTO_TRACE, context, QCString::find(), handleLinkedWord(), QCString::mid(), and parent().

Referenced by DocParamList::parse().

◆ handlePendingStyleCommands()

void DocParser::handlePendingStyleCommands ( DocNodeVariant * parent,
DocNodeList & children )

Called at the end of a paragraph to close all open style changes (e.g. a without a ). The closed styles are pushed onto a stack and entered again at the start of a new paragraph.

Definition at line 685 of file docparser.cpp.

686{
687 AUTO_TRACE();
688 if (!context.styleStack.empty())
689 {
690 const DocStyleChange *sc = &std::get<DocStyleChange>(*context.styleStack.top());
691 while (sc && sc->position()>=context.nodeStack.size())
692 { // there are unclosed style modifiers in the paragraph
693 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),
694 sc->style(),sc->tagName(),FALSE);
695 context.initialStyleStack.push(context.styleStack.top());
696 context.styleStack.pop();
697 sc = !context.styleStack.empty() ? &std::get<DocStyleChange>(*context.styleStack.top()) : nullptr;
698 }
699 }
700}
size_t position() const
Definition docnode.h:310

References DocNodeList::append(), AUTO_TRACE, context, FALSE, parent(), DocStyleChange::position(), DocStyleChange::style(), and DocStyleChange::tagName().

Referenced by defaultHandleTitleAndSize(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlDescTitle::parse(), DocHtmlHeader::parse(), DocInternalRef::parse(), DocLink::parse(), DocPara::parse(), DocRef::parse(), DocSecRefItem::parse(), DocTitle::parse(), and DocVhdlFlow::parse().

◆ handlePrefix()

void DocParser::handlePrefix ( DocNodeVariant * parent,
DocNodeList & children )

Definition at line 976 of file docparser.cpp.

977{
978 AUTO_TRACE();
979 Token tok=tokenizer.lex();
980 if (!tok.is(TokenRetval::TK_WHITESPACE))
981 {
982 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command", context.token->name);
983 return;
984 }
985 tokenizer.setStatePrefix();
986 tok=tokenizer.lex();
987 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
988 {
989 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected end of comment block while parsing the "
990 "argument of command {}",context.token->name);
991 return;
992 }
993 else if (!tok.is(TokenRetval::TK_WORD))
994 {
995 warn_doc_error(context.fileName,tokenizer.getLineNr(),"unexpected token {} as the argument of {}",
996 tok.to_string(),context.token->name);
997 return;
998 }
999 context.prefix = context.token->name;
1000 tokenizer.setStatePara();
1001}

References AUTO_TRACE, context, Token::is(), Token::is_any_of(), parent(), Token::to_string(), tokenizer, and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleStyleArgument()

Token DocParser::handleStyleArgument ( DocNodeVariant * parent,
DocNodeList & children,
const QCString & cmdName )

Definition at line 569 of file docparser.cpp.

570{
571 AUTO_TRACE("cmdName={}",cmdName);
572 QCString saveCmdName = cmdName;
573 Token tok=tokenizer.lex();
574 if (!tok.is(TokenRetval::TK_WHITESPACE))
575 {
576 warn_doc_error(context.fileName,tokenizer.getLineNr(),"expected whitespace after \\{} command",
577 saveCmdName);
578 return tok;
579 }
580 tok = tokenizer.lex();
581 while (!tok.is_any_of(TokenRetval::TK_NONE, TokenRetval::TK_EOF, TokenRetval::TK_WHITESPACE,
582 TokenRetval::TK_NEWPARA, TokenRetval::TK_LISTITEM, TokenRetval::TK_ENDLIST)
583 )
584 {
585 static const reg::Ex specialChar(R"([.,|()\[\]:;?])");
586 if (tok.is(TokenRetval::TK_WORD) && context.token->name.length()==1 &&
587 reg::match(context.token->name.str(),specialChar))
588 {
589 // special character that ends the markup command
590 return tok;
591 }
592 if (!defaultHandleToken(parent,tok,children))
593 {
594 switch (tok.value())
595 {
596 case TokenRetval::TK_HTMLTAG:
597 if (insideLI(parent) && Mappers::htmlTagMapper->map(context.token->name)!=HtmlTagType::UNKNOWN && context.token->endTag)
598 {
599 // ignore </li> as the end of a style command
600 }
601 else
602 {
603 AUTO_TRACE_EXIT("end tok={}",tok.to_string());
604 return tok;
605 }
606 break;
607 default:
608 errorHandleDefaultToken(parent,tok,children,"\\" + saveCmdName + " command");
609 break;
610 }
611 break;
612 }
613 tok = tokenizer.lex();
614 }
615 AUTO_TRACE_EXIT("end tok={}",tok.to_string());
616 return (tok.is_any_of(TokenRetval::TK_NEWPARA,TokenRetval::TK_LISTITEM,TokenRetval::TK_ENDLIST)) ? tok : Token::make_RetVal_OK();
617}
bool insideLI(const DocNodeVariant *n)

References AUTO_TRACE, AUTO_TRACE_EXIT, context, defaultHandleToken(), errorHandleDefaultToken(), Mappers::htmlTagMapper, insideLI(), Token::is(), Token::is_any_of(), reg::match(), parent(), Token::to_string(), tokenizer, UNKNOWN, Token::value(), and warn_doc_error.

Referenced by defaultHandleToken(), and DocPara::handleCommand().

◆ handleStyleEnter()

void DocParser::handleStyleEnter ( DocNodeVariant * parent,
DocNodeList & children,
DocStyleChange::Style s,
const QCString & tagName,
const HtmlAttribList * attribs )

Called when a style change starts. For instance a <b> command is encountered.

Definition at line 622 of file docparser.cpp.

624{
625 AUTO_TRACE("tagName={}",tagName);
626 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),s,tagName,TRUE,
627 context.fileName,tokenizer.getLineNr(),attribs);
628 context.styleStack.push(&children.back());
630}
T & back()
access the last element
Definition growvector.h:135

References DocNodeList::append(), AUTO_TRACE, GrowVector< T >::back(), context, parent(), tokenizer, TRUE, and DocStyleChange::Typewriter.

Referenced by defaultHandleToken(), DocPara::handleHtmlStartTag(), and handleInitialStyleCommands().

◆ handleStyleLeave()

void DocParser::handleStyleLeave ( DocNodeVariant * parent,
DocNodeList & children,
DocStyleChange::Style s,
const QCString & tagName )

Called when a style change ends. For instance a </b> command is encountered.

Definition at line 635 of file docparser.cpp.

637{
638 AUTO_TRACE("tagName={}",tagName);
639 QCString tagNameLower = QCString(tagName).lower();
640
641 auto topStyleChange = [](const DocStyleChangeStack &stack) -> const DocStyleChange &
642 {
643 return std::get<DocStyleChange>(*stack.top());
644 };
645
646 if (context.styleStack.empty() || // no style change
647 topStyleChange(context.styleStack).style()!=s || // wrong style change
648 topStyleChange(context.styleStack).tagName()!=tagNameLower || // wrong style change
649 topStyleChange(context.styleStack).position()!=context.nodeStack.size() // wrong position
650 )
651 {
652 if (context.styleStack.empty())
653 {
654 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{0}> tag without matching <{0}>",tagName);
655 }
656 else if (topStyleChange(context.styleStack).tagName()!=tagNameLower ||
657 topStyleChange(context.styleStack).style()!=s)
658 {
659 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{}> tag while expecting </{}>",
660 tagName,topStyleChange(context.styleStack).tagName());
661 }
662 else
663 {
664 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found </{}> at different nesting level ({}) than expected ({})",
665 tagName,context.nodeStack.size(),topStyleChange(context.styleStack).position());
666 }
667 }
668 else // end the section
669 {
670 children.append<DocStyleChange>(
671 this,parent,context.nodeStack.size(),s,
672 topStyleChange(context.styleStack).tagName(),FALSE);
673 context.styleStack.pop();
674 }
676 {
677 context.inCodeStyle = false;
678 }
679}
IterableStack< const DocNodeVariant * > DocStyleChangeStack
Definition docparser_p.h:55

References DocNodeList::append(), AUTO_TRACE, context, FALSE, QCString::lower(), parent(), tokenizer, DocStyleChange::Typewriter, and warn_doc_error.

Referenced by defaultHandleToken(), DocPara::handleHtmlEndTag(), and DocPara::handleHtmlStartTag().

◆ handleUnclosedStyleCommands()

void DocParser::handleUnclosedStyleCommands ( )

Definition at line 758 of file docparser.cpp.

759{
760 AUTO_TRACE();
761 if (!context.initialStyleStack.empty())
762 {
763 QCString tagName = std::get<DocStyleChange>(*context.initialStyleStack.top()).tagName();
764 QCString fileName = std::get<DocStyleChange>(*context.initialStyleStack.top()).fileName();
765 int lineNr = std::get<DocStyleChange>(*context.initialStyleStack.top()).lineNr();
766 context.initialStyleStack.pop();
768 if (lineNr != -1)
769 {
770 warn_doc_error(context.fileName,tokenizer.getLineNr(),
771 "end of comment block while expecting "
772 "command </{}> (Probable start '{}' at line {})",tagName, fileName, lineNr);
773 }
774 else
775 {
776 warn_doc_error(context.fileName,tokenizer.getLineNr(),
777 "end of comment block while expecting command </{}>",tagName);
778 }
779 }
780}
void handleUnclosedStyleCommands()

References AUTO_TRACE, context, handleUnclosedStyleCommands(), tokenizer, and warn_doc_error.

Referenced by handleUnclosedStyleCommands(), DocRoot::parse(), and DocText::parse().

◆ internalValidatingParseDoc()

Token DocParser::internalValidatingParseDoc ( DocNodeVariant * parent,
DocNodeList & children,
const QCString & doc )

Definition at line 1620 of file docparser.cpp.

1622{
1623 AUTO_TRACE();
1624 Token retval = Token::make_RetVal_OK();
1625
1626 if (doc.isEmpty()) return retval;
1627
1628 tokenizer.init(doc.data(),context.fileName,context.markdownSupport,context.insideHtmlLink);
1629
1630 // first parse any number of paragraphs
1631 bool isFirst=TRUE;
1632 DocPara *lastPar=!children.empty() ? std::get_if<DocPara>(&children.back()): nullptr;
1633 if (lastPar)
1634 { // last child item was a paragraph
1635 isFirst=FALSE;
1636 }
1637 do
1638 {
1639 children.append<DocPara>(this,parent);
1640 DocPara *par = children.get_last<DocPara>();
1641 if (isFirst) { par->markFirst(); isFirst=FALSE; }
1642 retval=par->parse();
1643 if (!par->isEmpty())
1644 {
1645 if (lastPar) lastPar->markLast(FALSE);
1646 lastPar=par;
1647 }
1648 else
1649 {
1650 children.pop_back();
1651 }
1652 } while (retval.is(TokenRetval::TK_NEWPARA));
1653 if (lastPar) lastPar->markLast();
1654
1655 AUTO_TRACE_EXIT("isFirst={} isLast={}",lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1656 return retval;
1657}
bool isLast() const
Definition docnode.h:1088
void markLast(bool v=TRUE)
Definition docnode.h:1086
bool isFirst() const
Definition docnode.h:1087
void pop_back()
removes the last element
Definition growvector.h:115
bool empty() const
checks whether the container is empty
Definition growvector.h:140
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_EXIT, GrowVector< T >::back(), context, QCString::data(), GrowVector< T >::empty(), FALSE, DocNodeList::get_last(), Token::is(), QCString::isEmpty(), DocPara::isFirst(), DocPara::isLast(), DocPara::markLast(), parent(), GrowVector< T >::pop_back(), tokenizer, and TRUE.

Referenced by DocPara::handleInheritDoc(), DocRef::parse(), DocXRefItem::parse(), DocTitle::parseFromString(), and DocSimpleSect::parseRcs().

◆ popContext()

void DocParser::popContext ( )

Definition at line 74 of file docparser.cpp.

75{
76 auto &ctx = contextStack.top();
77 context = ctx;
78 tokenizer.setLineNr(ctx.lineNo);
79 contextStack.pop();
80 tokenizer.popContext();
81 context.token = tokenizer.token();
82
83 //QCString indent;
84 //indent.fill(' ',contextStack.size()*2+2);
85 //printf("%sdocParserPopContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
86}
std::stack< DocParserContext > contextStack

References context, contextStack, and tokenizer.

Referenced by DocPara::handleInheritDoc(), DocRef::parse(), DocXRefItem::parse(), DocTitle::parseFromString(), and DocSimpleSect::parseRcs().

◆ processCopyDoc()

QCString DocParser::processCopyDoc ( const char * data,
size_t & len )

Definition at line 1815 of file docparser.cpp.

1816{
1817 AUTO_TRACE("data={} len={}",Trace::trunc(data),len);
1818 GrowBuf buf;
1819 size_t i=0;
1820 int lineNr = tokenizer.getLineNr();
1821 while (i<len)
1822 {
1823 char c = data[i];
1824 if (c=='@' || c=='\\') // look for a command
1825 {
1826 bool isBrief=TRUE;
1827 size_t j=isCopyBriefOrDetailsCmd(data,i,len,isBrief);
1828 if (j>0)
1829 {
1830 // skip whitespace
1831 while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
1832 // extract the argument
1833 QCString id = extractCopyDocId(data,j,len);
1834 const Definition *def = nullptr;
1835 QCString doc,brief;
1836 //printf("resolving docs='%s'\n",qPrint(id));
1837 bool found = findDocsForMemberOrCompound(id,&doc,&brief,&def);
1838 if (found && def->isReference())
1839 {
1840 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1841 "@copy{} or @copydoc target '{}' found but is from a tag file, skipped",
1842 isBrief?"brief":"details", id);
1843 }
1844 else if (found)
1845 {
1846 //printf("found it def=%p brief='%s' doc='%s' isBrief=%d\n",def,qPrint(brief),qPrint(doc),isBrief);
1847 auto it = std::find(context.copyStack.begin(),context.copyStack.end(),def);
1848 if (it==context.copyStack.end()) // definition not parsed earlier
1849 {
1850 QCString orgFileName = context.fileName;
1851 context.copyStack.push_back(def);
1852 auto addDocs = [&](const QCString &file_,int line_,const QCString &doc_)
1853 {
1854 buf.addStr(" \\ifile \""+file_+"\" ");
1855 buf.addStr("\\iline "+QCString().setNum(line_)+" \\ilinebr ");
1856 size_t len_ = doc_.length();
1857 buf.addStr(processCopyDoc(doc_.data(),len_));
1858 };
1859 if (isBrief)
1860 {
1861 addDocs(def->briefFile(),def->briefLine(),brief);
1862 }
1863 else
1864 {
1865 addDocs(def->docFile(),def->docLine(),doc);
1867 {
1868 const MemberDef *md = toMemberDef(def);
1869 const ArgumentList &docArgList = md->templateMaster() ?
1870 md->templateMaster()->argumentList() :
1871 md->argumentList();
1872 buf.addStr(inlineArgListToDoc(docArgList));
1873 }
1874 }
1875 context.copyStack.pop_back();
1876 buf.addStr(" \\ilinebr \\ifile \""+context.fileName+"\" ");
1877 buf.addStr("\\iline "+QCString().setNum(lineNr)+" ");
1878 }
1879 else
1880 {
1881 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1882 "Found recursive @copy{} or @copydoc relation for argument '{}'.",
1883 isBrief?"brief":"details",id);
1884 }
1885 }
1886 else
1887 {
1888 warn_doc_error(context.fileName,tokenizer.getLineNr(),
1889 "@copy{} or @copydoc target '{}' not found", isBrief?"brief":"details",id);
1890 }
1891 // skip over command
1892 i=j;
1893 }
1894 else
1895 {
1896 QCString endMarker;
1897 size_t k = isVerbatimSection(data,i,len,endMarker);
1898 if (k>0)
1899 {
1900 size_t orgPos = i;
1901 i=skipToEndMarker(data,k,len,endMarker);
1902 buf.addStr(data+orgPos,i-orgPos);
1903 // TODO: adjust lineNr
1904 }
1905 else
1906 {
1907 buf.addChar(c);
1908 i++;
1909 }
1910 }
1911 }
1912 else // not a command, just copy
1913 {
1914 buf.addChar(c);
1915 i++;
1916 lineNr += (c=='\n') ? 1 : 0;
1917 }
1918 }
1919 len = buf.getPos();
1920 buf.addChar(0);
1921 AUTO_TRACE_EXIT("result={}",Trace::trunc(buf.get()));
1922 return buf.get();
1923}
virtual int briefLine() const =0
virtual QCString briefFile() const =0
virtual bool isReference() const =0
QCString processCopyDoc(const char *data, size_t &len)
bool findDocsForMemberOrCompound(const QCString &commandName, QCString *pDoc, QCString *pBrief, const Definition **pDef)
size_t getPos() const
Definition growbuf.h:116
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
virtual const ArgumentList & argumentList() const =0
virtual const MemberDef * templateMaster() const =0
static QCString extractCopyDocId(const char *data, size_t &j, size_t len)
static size_t skipToEndMarker(const char *data, size_t i, size_t len, const QCString &endMarker)
static size_t isVerbatimSection(const char *data, size_t i, size_t len, QCString &endMarker)
static size_t isCopyBriefOrDetailsCmd(const char *data, size_t i, size_t len, bool &brief)
MemberDef * toMemberDef(Definition *d)
QCString trunc(const QCString &s, size_t numChars=15)
Definition trace.h:56
QCString inlineArgListToDoc(const ArgumentList &al)
Definition util.cpp:1157

References GrowBuf::addChar(), GrowBuf::addStr(), MemberDef::argumentList(), AUTO_TRACE, AUTO_TRACE_EXIT, Definition::briefFile(), Definition::briefLine(), context, Definition::definitionType(), Definition::docFile(), Definition::docLine(), extractCopyDocId(), findDocsForMemberOrCompound(), GrowBuf::get(), GrowBuf::getPos(), inlineArgListToDoc(), isCopyBriefOrDetailsCmd(), Definition::isReference(), isVerbatimSection(), processCopyDoc(), skipToEndMarker(), MemberDef::templateMaster(), tokenizer, toMemberDef(), TRUE, Trace::trunc(), Definition::TypeMember, and warn_doc_error.

Referenced by processCopyDoc(), and validatingParseDoc().

◆ pushContext()

void DocParser::pushContext ( )

Definition at line 60 of file docparser.cpp.

61{
62 //QCString indent;
63 //indent.fill(' ',contextStack.size()*2+2);
64 //printf("%sdocParserPushContext() count=%zu\n",qPrint(indent),context.nodeStack.size());
65
66 tokenizer.pushContext();
67 contextStack.emplace();
68 auto &ctx = contextStack.top();
69 ctx = context;
70 ctx.lineNo = tokenizer.getLineNr();
71 context.token = tokenizer.token();
72}

References context, contextStack, and tokenizer.

Referenced by DocPara::handleInheritDoc(), DocRef::parse(), DocXRefItem::parse(), DocTitle::parseFromString(), and DocSimpleSect::parseRcs().

◆ readTextFileByName()

void DocParser::readTextFileByName ( const QCString & file,
QCString & text )

Definition at line 1661 of file docparser.cpp.

1662{
1663 AUTO_TRACE("file={} text={}",file,text);
1664 bool ambig = false;
1665 QCString filePath = findFilePath(file,ambig);
1666 if (!filePath.isEmpty())
1667 {
1668 text = fileToString(filePath,Config_getBool(FILTER_SOURCE_FILES));
1669 if (ambig)
1670 {
1671 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file name '{}' is ambiguous"
1672 "Possible candidates:\n{}",file, showFileDefMatches(Doxygen::exampleNameLinkedMap,file));
1673 }
1674 }
1675 else
1676 {
1677 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file '{}' is not found. "
1678 "Check your EXAMPLE_PATH",file);
1679 }
1680}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:103
QCString findFilePath(const QCString &file, bool &ambig)
Definition util.cpp:3502
QCString fileToString(const QCString &name, bool filter, bool isSourceCode)
Definition util.cpp:1442

References AUTO_TRACE, Config_getBool, context, Doxygen::exampleNameLinkedMap, fileToString(), findFilePath(), QCString::isEmpty(), showFileDefMatches(), tokenizer, and warn_doc_error.

Referenced by DocInclude::parse().

Member Data Documentation

◆ context

DocParserContext DocParser::context

Definition at line 142 of file docparser_p.h.

Referenced by DocSimpleSect::appendLinkWord(), checkArgumentName(), checkIfHtmlEndTagEndsAutoList(), checkRetvalName(), checkUnOrMultipleDocumentedParams(), createRef(), defaultHandleTitleAndSize(), defaultHandleToken(), errorHandleDefaultToken(), findAndCopyImage(), findDocsForMemberOrCompound(), handleAHref(), handleAnchor(), DocPara::handleCite(), DocPara::handleCommand(), DocPara::handleDoxyConfig(), DocPara::handleEmoji(), DocPara::handleFile(), DocPara::handleHtmlStartTag(), DocPara::handleIFile(), handleImage(), handleImg(), DocPara::handleInclude(), DocPara::handleIncludeOperator(), DocPara::handleInheritDoc(), handleInitialStyleCommands(), handleInternalRef(), DocPara::handleLink(), handleLinkedWord(), handleParameterType(), handlePendingStyleCommands(), handlePrefix(), DocPara::handleRef(), DocPara::handleSection(), DocPara::handleShowDate(), DocPara::handleStartCode(), handleStyleArgument(), handleStyleEnter(), handleStyleLeave(), handleUnclosedStyleCommands(), DocPara::handleXRefItem(), DocPara::injectToken(), internalValidatingParseDoc(), DocAutoList::parse(), DocHRef::parse(), DocHtmlDescData::parse(), DocHtmlDescList::parse(), DocHtmlDescTitle::parse(), DocHtmlHeader::parse(), DocHtmlList::parse(), DocHtmlRow::parse(), DocHtmlTable::parse(), DocInclude::parse(), DocIncOperator::parse(), DocIndexEntry::parse(), DocInternal::parse(), DocLink::parse(), DocPara::parse(), DocParamList::parse(), DocRef::parse(), DocRoot::parse(), DocSecRefList::parse(), DocSection::parse(), DocText::parse(), DocTitle::parseFromString(), DocSimpleSect::parseRcs(), DocHtmlList::parseXml(), DocHtmlRow::parseXml(), DocHtmlTable::parseXml(), DocParamList::parseXml(), popContext(), processCopyDoc(), pushContext(), readTextFileByName(), skipSpacesForTable(), validatingParseDoc(), validatingParseText(), and validatingParseTitle().

◆ contextStack

std::stack< DocParserContext > DocParser::contextStack

Definition at line 141 of file docparser_p.h.

Referenced by popContext(), and pushContext().

◆ tokenizer

DocTokenizer DocParser::tokenizer

Definition at line 143 of file docparser_p.h.

Referenced by checkIfHtmlEndTagEndsAutoList(), createRef(), defaultHandleTitleAndSize(), defaultHandleToken(), docFindSections(), errorHandleDefaultToken(), findAndCopyImage(), handleAHref(), handleAnchor(), DocPara::handleCite(), DocPara::handleCommand(), DocPara::handleDoxyConfig(), DocPara::handleEmoji(), DocPara::handleFile(), DocPara::handleHtmlEndTag(), DocPara::handleHtmlStartTag(), DocPara::handleIFile(), DocPara::handleILine(), handleImage(), handleImg(), DocPara::handleInclude(), DocPara::handleIncludeOperator(), handleInternalRef(), DocPara::handleLink(), handleLinkedWord(), handlePrefix(), DocPara::handleRef(), DocPara::handleSection(), DocPara::handleShowDate(), DocPara::handleStartCode(), handleStyleArgument(), handleStyleEnter(), handleStyleLeave(), handleUnclosedStyleCommands(), DocPara::handleXRefItem(), internalValidatingParseDoc(), DocAutoList::parse(), DocHRef::parse(), DocHtmlCaption::parse(), DocHtmlDescList::parse(), DocHtmlDescTitle::parse(), DocHtmlHeader::parse(), DocHtmlList::parse(), DocHtmlRow::parse(), DocHtmlSummary::parse(), DocIndexEntry::parse(), DocInternalRef::parse(), DocLink::parse(), DocPara::parse(), DocParamList::parse(), DocRef::parse(), DocRoot::parse(), DocSecRefItem::parse(), DocSecRefList::parse(), DocText::parse(), DocTitle::parse(), DocVhdlFlow::parse(), DocTitle::parseFromString(), DocHtmlList::parseXml(), DocHtmlRow::parseXml(), DocHtmlTable::parseXml(), popContext(), processCopyDoc(), pushContext(), readTextFileByName(), skipSpacesForTable(), validatingParseDoc(), validatingParseText(), and validatingParseTitle().


The documentation for this class was generated from the following files: