Skip to main content

The DocParser Class Reference

Declaration

class DocParser { ... }

Included Headers

#include <src/docparser_p.h>

Base class

classIDocParser

opaque parser interface More...

Public Member Functions Index

voidpushContext ()
voidpopContext ()
voidhandleImg (DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
TokeninternalValidatingParseDoc (DocNodeVariant *parent, DocNodeList &children, const QCString &doc)
QCStringprocessCopyDoc (const char *data, size_t &len)
QCStringfindAndCopyImage (const QCString &fileName, DocImage::Type type, bool doWarn=true)
voidcheckArgumentName ()
voidcheckRetvalName ()
voidcheckUnOrMultipleDocumentedParams ()
boolfindDocsForMemberOrCompound (const QCString &commandName, QCString *pDoc, QCString *pBrief, const Definition **pDef)
booldefaultHandleToken (DocNodeVariant *parent, Token tok, DocNodeList &children, bool handleWord=TRUE)
voiderrorHandleDefaultToken (DocNodeVariant *parent, Token tok, DocNodeList &children, const QCString &txt)
voiddefaultHandleTitleAndSize (const CommandType cmd, DocNodeVariant *parent, DocNodeList &children, QCString &width, QCString &height)
TokenhandleStyleArgument (DocNodeVariant *parent, DocNodeList &children, const QCString &cmdName)
voidhandleStyleEnter (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName, const HtmlAttribList *attribs)
voidhandleStyleLeave (DocNodeVariant *parent, DocNodeList &children, DocStyleChange::Style s, const QCString &tagName)
voidhandlePendingStyleCommands (DocNodeVariant *parent, DocNodeList &children)
voidhandleInitialStyleCommands (DocNodeVariant *parent, DocNodeList &children)
TokenhandleAHref (DocNodeVariant *parent, DocNodeList &children, const HtmlAttribList &tagHtmlAttribs)
voidhandleUnclosedStyleCommands ()
voidhandleLinkedWord (DocNodeVariant *parent, DocNodeList &children, bool ignoreAutoLinkFlag=FALSE)
voidhandleParameterType (DocNodeVariant *parent, DocNodeList &children, const QCString &paramTypes)
voidhandleInternalRef (DocNodeVariant *parent, DocNodeList &children)
voidhandleAnchor (DocNodeVariant *parent, DocNodeList &children)
voidhandlePrefix (DocNodeVariant *parent, DocNodeList &children)
voidhandleImage (DocNodeVariant *parent, DocNodeList &children)
voidreadTextFileByName (const QCString &file, QCString &text)

Public Member Attributes Index

std::stack< DocParserContext >contextStack
DocParserContextcontext
DocTokenizertokenizer

Definition at line 98 of file docparser_p.h.

Public Member Functions

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).

Declaration at line 108 of file docparser_p.h, 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);
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}

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.

Declaration at line 109 of file docparser_p.h, 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.

Declaration at line 110 of file docparser_p.h, 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()) +
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}

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)

Declaration at line 120 of file docparser_p.h, definition at line 1006 of file docparser.cpp.

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

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)

Declaration at line 115 of file docparser_p.h, definition at line 1208 of file docparser.cpp.

1209{
1210 AUTO_TRACE("token={} handleWord={}",tok.to_string(),handleWord);
1211 if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD,TokenRetval::TK_SYMBOL,TokenRetval::TK_URL,
1212 TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS,TokenRetval::TK_HTMLTAG)
1213 )
1214 {
1215 }
1216reparsetoken:
1217 QCString tokenName = context.token->name;
1218 AUTO_TRACE_ADD("tokenName={}",tokenName);
1219 switch (tok.value())
1220 {
1221 case TokenRetval::TK_COMMAND_AT:
1222 // fall through
1223 case TokenRetval::TK_COMMAND_BS:
1224 switch (Mappers::cmdMapper->map(tokenName))
1225 {
1228 break;
1231 break;
1234 break;
1237 break;
1240 break;
1243 break;
1246 break;
1249 break;
1252 break;
1256 break;
1261 break;
1264 break;
1267 break;
1270 break;
1273 break;
1276 break;
1279 break;
1282 break;
1284 {
1285 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,TRUE);
1286 tok=handleStyleArgument(parent,children,tokenName);
1287 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,FALSE);
1288 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1289 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1290 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1291 {
1292 AUTO_TRACE_ADD("CommandType::CMD_EMPHASIS: reparsing");
1293 goto reparsetoken;
1294 }
1295 }
1296 break;
1298 {
1299 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,TRUE);
1300 tok=handleStyleArgument(parent,children,tokenName);
1301 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,FALSE);
1302 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1303 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1304 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1305 {
1306 AUTO_TRACE_ADD("CommandType::CMD_BOLD: reparsing");
1307 goto reparsetoken;
1308 }
1309 }
1310 break;
1312 {
1313 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,TRUE);
1314 tok=handleStyleArgument(parent,children,tokenName);
1315 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,FALSE);
1316 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1317 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1318 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1319 {
1320 AUTO_TRACE_ADD("CommandType::CMD_CODE: reparsing");
1321 goto reparsetoken;
1322 }
1323 }
1324 break;
1326 {
1327 tokenizer.setStateHtmlOnly();
1328 tok = tokenizer.lex();
1329 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::HtmlOnly,context.isExample,context.exampleName,context.token->name=="block");
1330 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1331 {
1332 warn_doc_error(context.fileName,tokenizer.getLineNr(),"htmlonly section ended without end marker");
1333 }
1334 tokenizer.setStatePara();
1335 }
1336 break;
1338 {
1339 tokenizer.setStateManOnly();
1340 tok = tokenizer.lex();
1341 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::ManOnly,context.isExample,context.exampleName);
1342 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1343 {
1344 warn_doc_error(context.fileName,tokenizer.getLineNr(),"manonly section ended without end marker");
1345 }
1346 tokenizer.setStatePara();
1347 }
1348 break;
1350 {
1351 tokenizer.setStateRtfOnly();
1352 tok = tokenizer.lex();
1353 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::RtfOnly,context.isExample,context.exampleName);
1354 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1355 {
1356 warn_doc_error(context.fileName,tokenizer.getLineNr(),"rtfonly section ended without end marker");
1357 }
1358 tokenizer.setStatePara();
1359 }
1360 break;
1362 {
1363 tokenizer.setStateLatexOnly();
1364 tok = tokenizer.lex();
1365 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::LatexOnly,context.isExample,context.exampleName);
1366 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1367 {
1368 warn_doc_error(context.fileName,tokenizer.getLineNr(),"latexonly section ended without end marker");
1369 }
1370 tokenizer.setStatePara();
1371 }
1372 break;
1374 {
1375 tokenizer.setStateXmlOnly();
1376 tok = tokenizer.lex();
1377 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::XmlOnly,context.isExample,context.exampleName);
1378 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1379 {
1380 warn_doc_error(context.fileName,tokenizer.getLineNr(),"xmlonly section ended without end marker");
1381 }
1382 tokenizer.setStatePara();
1383 }
1384 break;
1386 {
1387 tokenizer.setStateDbOnly();
1388 tok = tokenizer.lex();
1389 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::DocbookOnly,context.isExample,context.exampleName);
1390 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1391 {
1392 warn_doc_error(context.fileName,tokenizer.getLineNr(),"docbookonly section ended without end marker");
1393 }
1394 tokenizer.setStatePara();
1395 }
1396 break;
1398 {
1399 children.append<DocFormula>(this,parent,context.token->id);
1400 }
1401 break;
1404 {
1405 handleAnchor(parent,children);
1406 }
1407 break;
1409 {
1410 handlePrefix(parent,children);
1411 }
1412 break;
1414 {
1415 handleInternalRef(parent,children);
1416 tokenizer.setStatePara();
1417 }
1418 break;
1420 {
1421 tokenizer.setStateSetScope();
1422 (void)tokenizer.lex();
1423 context.context = context.token->name;
1424 //printf("Found scope='%s'\n",qPrint(context.context));
1425 tokenizer.setStatePara();
1426 }
1427 break;
1429 handleImage(parent,children);
1430 break;
1432 tokenizer.pushState();
1433 tokenizer.setStateILine();
1434 (void)tokenizer.lex();
1435 tokenizer.popState();
1436 break;
1438 tokenizer.pushState();
1439 tokenizer.setStateIFile();
1440 (void)tokenizer.lex();
1441 tokenizer.popState();
1442 break;
1443 default:
1444 return FALSE;
1445 }
1446 break;
1447 case TokenRetval::TK_HTMLTAG:
1448 {
1449 auto handleEnterLeaveStyle = [this,&parent,&children,&tokenName](DocStyleChange::Style style) {
1450 if (!context.token->endTag)
1451 {
1452 handleStyleEnter(parent,children,style,tokenName,&context.token->attribs);
1453 }
1454 else
1455 {
1456 handleStyleLeave(parent,children,style,tokenName);
1457 }
1458 };
1459 switch (Mappers::htmlTagMapper->map(tokenName))
1460 {
1462 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <div> tag in heading");
1463 break;
1465 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <pre> tag in heading");
1466 break;
1468 handleEnterLeaveStyle(DocStyleChange::Span);
1469 break;
1471 handleEnterLeaveStyle(DocStyleChange::Bold);
1472 break;
1474 handleEnterLeaveStyle(DocStyleChange::S);
1475 break;
1477 handleEnterLeaveStyle(DocStyleChange::Strike);
1478 break;
1480 handleEnterLeaveStyle(DocStyleChange::Del);
1481 break;
1483 handleEnterLeaveStyle(DocStyleChange::Underline);
1484 break;
1486 handleEnterLeaveStyle(DocStyleChange::Ins);
1487 break;
1490 handleEnterLeaveStyle(DocStyleChange::Code);
1491 break;
1493 handleEnterLeaveStyle(DocStyleChange::Kbd);
1494 break;
1496 handleEnterLeaveStyle(DocStyleChange::Typewriter);
1497 break;
1499 handleEnterLeaveStyle(DocStyleChange::Italic);
1500 break;
1502 handleEnterLeaveStyle(DocStyleChange::Subscript);
1503 break;
1505 handleEnterLeaveStyle(DocStyleChange::Superscript);
1506 break;
1508 handleEnterLeaveStyle(DocStyleChange::Center);
1509 break;
1511 handleEnterLeaveStyle(DocStyleChange::Small);
1512 break;
1514 handleEnterLeaveStyle(DocStyleChange::Cite);
1515 break;
1517 if (!context.token->endTag)
1518 {
1519 handleImg(parent,children,context.token->attribs);
1520 }
1521 break;
1522 default:
1523 return FALSE;
1524 break;
1525 }
1526 }
1527 break;
1528 case TokenRetval::TK_SYMBOL:
1529 {
1532 {
1533 children.append<DocSymbol>(this,parent,s);
1534 }
1535 else
1536 {
1537 return FALSE;
1538 }
1539 }
1540 break;
1541 case TokenRetval::TK_WHITESPACE:
1542 case TokenRetval::TK_NEWPARA:
1543handlepara:
1544 if (insidePRE(parent) || !children.empty())
1545 {
1546 children.append<DocWhiteSpace>(this,parent,context.token->chars);
1547 }
1548 break;
1549 case TokenRetval::TK_LNKWORD:
1550 if (handleWord)
1551 {
1552 handleLinkedWord(parent,children);
1553 }
1554 else
1555 return FALSE;
1556 break;
1557 case TokenRetval::TK_WORD:
1558 if (handleWord)
1559 {
1560 children.append<DocWord>(this,parent,context.token->name);
1561 }
1562 else
1563 return FALSE;
1564 break;
1565 case TokenRetval::TK_URL:
1566 if (context.insideHtmlLink)
1567 {
1568 children.append<DocWord>(this,parent,context.token->name);
1569 }
1570 else
1571 {
1572 children.append<DocURL>(this,parent,context.token->name,context.token->isEMailAddr);
1573 }
1574 break;
1575 default:
1576 return FALSE;
1577 }
1578 return TRUE;
1579}

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)

Declaration at line 118 of file docparser_p.h, definition at line 536 of file docparser.cpp.

537 DocNodeList &children,const QCString &txt)
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}

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).

Declaration at line 107 of file docparser_p.h, definition at line 94 of file docparser.cpp.

95{
96 QCString result;
97 bool ambig = false;
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 {
157 Doxygen::indexList->addImageFile(result);
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}

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
TRUE

if name was found.

FALSE

if name was not found.

Declaration at line 111 of file docparser_p.h, definition at line 383 of file docparser.cpp.

384 QCString *pDoc,
385 QCString *pBrief,
386 const Definition **pDef)
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;
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}

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)

Declaration at line 130 of file docparser_p.h, definition at line 708 of file docparser.cpp.

709 const HtmlAttribList &tagHtmlAttribs)
710{
711 AUTO_TRACE();
712 size_t index=0;
713 Token retval = Token::make_RetVal_OK();
714 for (const auto &opt : tagHtmlAttribs)
715 {
716 if (opt.name=="name" || opt.name=="id") // <a name=label> or <a id=label> tag
717 {
718 if (!opt.value.isEmpty())
719 {
720 children.append<DocAnchor>(this,parent,opt.value,TRUE);
721 break; // stop looking for other tag attribs
722 }
723 else
724 {
725 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <a> tag with name option but without value!");
726 }
727 }
728 else if (opt.name=="href") // <a href=url>..</a> tag
729 {
730 // copy attributes
731 HtmlAttribList attrList = tagHtmlAttribs;
732 // and remove the href attribute
733 attrList.erase(attrList.begin()+index);
734 QCString relPath;
735 if (opt.value.at(0) != '#') relPath = context.relPath;
736 children.append<DocHRef>(this, parent, attrList,
737 opt.value, relPath,
739 context.insideHtmlLink=TRUE;
740 retval = children.get_last<DocHRef>()->parse();
741 context.insideHtmlLink=FALSE;
742 tokenizer.setStatePara();
743 break;
744 }
745 else // unsupported option for tag a
746 {
747 }
748 ++index;
749 }
750 return retval;
751}

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)

Declaration at line 135 of file docparser_p.h, definition at line 942 of file docparser.cpp.

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

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)

Declaration at line 137 of file docparser_p.h, definition at line 1090 of file docparser.cpp.

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

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)

Declaration at line 103 of file docparser_p.h, definition at line 1583 of file docparser.cpp.

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

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)

Declaration at line 129 of file docparser_p.h, definition at line 697 of file docparser.cpp.

698{
699 AUTO_TRACE();
700 while (!context.initialStyleStack.empty())
701 {
702 const DocStyleChange &sc = std::get<DocStyleChange>(*context.initialStyleStack.top());
703 handleStyleEnter(parent,children,sc.style(),sc.tagName(),&sc.attribs());
704 context.initialStyleStack.pop();
705 }
706}

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)

Declaration at line 134 of file docparser_p.h, definition at line 920 of file docparser.cpp.

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

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)

Declaration at line 132 of file docparser_p.h, definition at line 777 of file docparser.cpp.

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

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)

Declaration at line 133 of file docparser_p.h, definition at line 896 of file docparser.cpp.

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

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.

Declaration at line 128 of file docparser_p.h, definition at line 680 of file docparser.cpp.

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

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)

Declaration at line 136 of file docparser_p.h, definition at line 970 of file docparser.cpp.

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

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)

Declaration at line 122 of file docparser_p.h, 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}

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.

Declaration at line 124 of file docparser_p.h, definition at line 622 of file docparser.cpp.

623 DocStyleChange::Style s,const QCString &tagName,const HtmlAttribList *attribs)
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());
629}

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

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.

Declaration at line 126 of file docparser_p.h, definition at line 634 of file docparser.cpp.

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

References DocNodeList::append, AUTO_TRACE, context, FALSE, QCString::lower, parent, tokenizer and warn_doc_error.

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

handleUnclosedStyleCommands()

void DocParser::handleUnclosedStyleCommands ()

Declaration at line 131 of file docparser_p.h, definition at line 753 of file docparser.cpp.

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

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)

Declaration at line 104 of file docparser_p.h, definition at line 1614 of file docparser.cpp.

1615 const QCString &doc)
1616{
1617 AUTO_TRACE();
1618 Token retval = Token::make_RetVal_OK();
1619
1620 if (doc.isEmpty()) return retval;
1621
1622 tokenizer.init(doc.data(),context.fileName,context.markdownSupport,context.insideHtmlLink);
1623
1624 // first parse any number of paragraphs
1625 bool isFirst=TRUE;
1626 DocPara *lastPar=!children.empty() ? std::get_if<DocPara>(&children.back()): nullptr;
1627 if (lastPar)
1628 { // last child item was a paragraph
1629 isFirst=FALSE;
1630 }
1631 do
1632 {
1633 children.append<DocPara>(this,parent);
1634 DocPara *par = children.get_last<DocPara>();
1635 if (isFirst) { par->markFirst(); isFirst=FALSE; }
1636 retval=par->parse();
1637 if (!par->isEmpty())
1638 {
1639 if (lastPar) lastPar->markLast(FALSE);
1640 lastPar=par;
1641 }
1642 else
1643 {
1644 children.pop_back();
1645 }
1646 } while (retval.is(TokenRetval::TK_NEWPARA));
1647 if (lastPar) lastPar->markLast();
1648
1649 AUTO_TRACE_EXIT("isFirst={} isLast={}",lastPar?lastPar->isFirst():-1,lastPar?lastPar->isLast():-1);
1650 return retval;
1651}

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 ()

Declaration at line 102 of file docparser_p.h, 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}

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)

Declaration at line 106 of file docparser_p.h, definition at line 1809 of file docparser.cpp.

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

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 ()

Declaration at line 101 of file docparser_p.h, 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)

Declaration at line 138 of file docparser_p.h, definition at line 1655 of file docparser.cpp.

1656{
1657 AUTO_TRACE("file={} text={}",file,text);
1658 bool ambig = false;
1659 QCString filePath = findFilePath(file,ambig);
1660 if (!filePath.isEmpty())
1661 {
1662 text = fileToString(filePath,Config_getBool(FILTER_SOURCE_FILES));
1663 if (ambig)
1664 {
1665 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file name '{}' is ambiguous"
1666 "Possible candidates:\n{}",file, showFileDefMatches(Doxygen::exampleNameLinkedMap,file));
1667 }
1668 }
1669 else
1670 {
1671 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file '{}' is not found. "
1672 "Check your EXAMPLE_PATH",file);
1673 }
1674}

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

Referenced by DocInclude::parse.

Public Member Attributes

context

DocParserContext DocParser::context

Definition at line 141 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, validatingParseDoc, validatingParseText and validatingParseTitle.

contextStack

std::stack< DocParserContext > DocParser::contextStack

Definition at line 140 of file docparser_p.h.

140 std::stack< DocParserContext > contextStack;

Referenced by popContext and pushContext.

tokenizer

DocTokenizer DocParser::tokenizer

Definition at line 142 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, DocHtmlTable::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, validatingParseDoc, validatingParseText and validatingParseTitle.


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


Generated via doxygen2docusaurus by Doxygen 1.14.0.