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 98 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 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}
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 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 {
1227 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_BSlash);
1228 break;
1230 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_At);
1231 break;
1233 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Less);
1234 break;
1236 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Greater);
1237 break;
1239 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Amp);
1240 break;
1242 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dollar);
1243 break;
1245 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Hash);
1246 break;
1248 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_DoubleColon);
1249 break;
1251 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Percent);
1252 break;
1254 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1255 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1256 break;
1258 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1259 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1260 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1261 break;
1263 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quot);
1264 break;
1266 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dot);
1267 break;
1269 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Exclam);
1270 break;
1272 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quest);
1273 break;
1275 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Plus);
1276 break;
1278 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1279 break;
1281 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Equal);
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;
1489 case HtmlTagType::XML_C:
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}
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:3542
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:6370
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:3416

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 708 of file docparser.cpp.

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,
738 convertNameToFile(context.fileName, FALSE, TRUE));
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}
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:4017

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

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}
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:7129

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

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

Definition at line 777 of file docparser.cpp.

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;
801 FileDef *fd = findFileDef(Doxygen::inputNameLinkedMap,context.fileName,ambig);
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(),
825 member->briefDescriptionAsTooltip());
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(),
881 cd->getOutputFileBase(),
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}
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:1932
GroupDef * toGroupDef(Definition *d)
QCString linkToText(SrcLangExt lang, const QCString &link, bool isFileName)
Definition util.cpp:3220
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 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.

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

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());
629}
T & back()
access the last element
Definition growvector.h:135

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.

Definition at line 634 of file docparser.cpp.

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}
IterableStack< const DocNodeVariant * > DocStyleChangeStack
Definition docparser_p.h:55

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

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}
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 1614 of file docparser.cpp.

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}
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 1809 of file docparser.cpp.

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() ?
1864 md->templateMaster()->argumentList() :
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}
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 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}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:103
QCString findFilePath(const QCString &file, bool &ambig)
Definition util.cpp:3499
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 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(), skipSpacesForTable(), validatingParseDoc(), validatingParseText(), and validatingParseTitle().

◆ contextStack

std::stack< DocParserContext > DocParser::contextStack

Definition at line 140 of file docparser_p.h.

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