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 97 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
bool found
Definition util.cpp:984
QCString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:1201

References argListToString(), Config_getBool, context, Definition::docFile(), Definition::docLine(), ArgumentList::empty(), end(), QCString::endsWith(), FALSE, found, 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 1007 of file docparser.cpp.

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

1210{
1211 AUTO_TRACE("token={} handleWord={}",tok.to_string(),handleWord);
1212 if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_LNKWORD,TokenRetval::TK_SYMBOL,TokenRetval::TK_URL,
1213 TokenRetval::TK_COMMAND_AT,TokenRetval::TK_COMMAND_BS,TokenRetval::TK_HTMLTAG)
1214 )
1215 {
1216 }
1217reparsetoken:
1218 QCString tokenName = context.token->name;
1219 AUTO_TRACE_ADD("tokenName={}",tokenName);
1220 switch (tok.value())
1221 {
1222 case TokenRetval::TK_COMMAND_AT:
1223 // fall through
1224 case TokenRetval::TK_COMMAND_BS:
1225 switch (Mappers::cmdMapper->map(tokenName))
1226 {
1228 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_BSlash);
1229 break;
1231 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_At);
1232 break;
1234 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Less);
1235 break;
1237 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Greater);
1238 break;
1240 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Amp);
1241 break;
1243 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dollar);
1244 break;
1246 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Hash);
1247 break;
1249 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_DoubleColon);
1250 break;
1252 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Percent);
1253 break;
1255 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1256 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1257 break;
1259 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1260 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1261 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1262 break;
1264 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quot);
1265 break;
1267 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Dot);
1268 break;
1270 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Exclam);
1271 break;
1273 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Quest);
1274 break;
1276 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Plus);
1277 break;
1279 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Minus);
1280 break;
1282 children.append<DocSymbol>(this,parent,HtmlEntityMapper::Sym_Equal);
1283 break;
1285 {
1286 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,TRUE);
1287 tok=handleStyleArgument(parent,children,tokenName);
1288 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Italic,tokenName,FALSE);
1289 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1290 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1291 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1292 {
1293 AUTO_TRACE_ADD("CommandType::CMD_EMPHASIS: reparsing");
1294 goto reparsetoken;
1295 }
1296 }
1297 break;
1299 {
1300 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,TRUE);
1301 tok=handleStyleArgument(parent,children,tokenName);
1302 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Bold,tokenName,FALSE);
1303 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1304 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1305 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1306 {
1307 AUTO_TRACE_ADD("CommandType::CMD_BOLD: reparsing");
1308 goto reparsetoken;
1309 }
1310 }
1311 break;
1313 {
1314 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,TRUE);
1315 tok=handleStyleArgument(parent,children,tokenName);
1316 children.append<DocStyleChange>(this,parent,context.nodeStack.size(),DocStyleChange::Code,tokenName,FALSE);
1317 if (!tok.is(TokenRetval::TK_WORD)) children.append<DocWhiteSpace>(this,parent," ");
1318 if (tok.is(TokenRetval::TK_NEWPARA)) goto handlepara;
1319 else if (tok.is_any_of(TokenRetval::TK_WORD,TokenRetval::TK_HTMLTAG))
1320 {
1321 AUTO_TRACE_ADD("CommandType::CMD_CODE: reparsing");
1322 goto reparsetoken;
1323 }
1324 }
1325 break;
1327 {
1328 tokenizer.setStateHtmlOnly();
1329 tok = tokenizer.lex();
1330 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::HtmlOnly,context.isExample,context.exampleName,context.token->name=="block");
1331 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1332 {
1333 warn_doc_error(context.fileName,tokenizer.getLineNr(),"htmlonly section ended without end marker");
1334 }
1335 tokenizer.setStatePara();
1336 }
1337 break;
1339 {
1340 tokenizer.setStateManOnly();
1341 tok = tokenizer.lex();
1342 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::ManOnly,context.isExample,context.exampleName);
1343 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1344 {
1345 warn_doc_error(context.fileName,tokenizer.getLineNr(),"manonly section ended without end marker");
1346 }
1347 tokenizer.setStatePara();
1348 }
1349 break;
1351 {
1352 tokenizer.setStateRtfOnly();
1353 tok = tokenizer.lex();
1354 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::RtfOnly,context.isExample,context.exampleName);
1355 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1356 {
1357 warn_doc_error(context.fileName,tokenizer.getLineNr(),"rtfonly section ended without end marker");
1358 }
1359 tokenizer.setStatePara();
1360 }
1361 break;
1363 {
1364 tokenizer.setStateLatexOnly();
1365 tok = tokenizer.lex();
1366 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::LatexOnly,context.isExample,context.exampleName);
1367 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1368 {
1369 warn_doc_error(context.fileName,tokenizer.getLineNr(),"latexonly section ended without end marker");
1370 }
1371 tokenizer.setStatePara();
1372 }
1373 break;
1375 {
1376 tokenizer.setStateXmlOnly();
1377 tok = tokenizer.lex();
1378 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::XmlOnly,context.isExample,context.exampleName);
1379 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1380 {
1381 warn_doc_error(context.fileName,tokenizer.getLineNr(),"xmlonly section ended without end marker");
1382 }
1383 tokenizer.setStatePara();
1384 }
1385 break;
1387 {
1388 tokenizer.setStateDbOnly();
1389 tok = tokenizer.lex();
1390 children.append<DocVerbatim>(this,parent,context.context,context.token->verb,DocVerbatim::DocbookOnly,context.isExample,context.exampleName);
1391 if (tok.is_any_of(TokenRetval::TK_NONE,TokenRetval::TK_EOF))
1392 {
1393 warn_doc_error(context.fileName,tokenizer.getLineNr(),"docbookonly section ended without end marker");
1394 }
1395 tokenizer.setStatePara();
1396 }
1397 break;
1399 {
1400 children.append<DocFormula>(this,parent,context.token->id);
1401 }
1402 break;
1405 {
1406 handleAnchor(parent,children);
1407 }
1408 break;
1410 {
1411 handlePrefix(parent,children);
1412 }
1413 break;
1415 {
1416 handleInternalRef(parent,children);
1417 tokenizer.setStatePara();
1418 }
1419 break;
1421 {
1422 tokenizer.setStateSetScope();
1423 (void)tokenizer.lex();
1424 context.context = context.token->name;
1425 //printf("Found scope='%s'\n",qPrint(context.context));
1426 tokenizer.setStatePara();
1427 }
1428 break;
1430 handleImage(parent,children);
1431 break;
1433 tokenizer.pushState();
1434 tokenizer.setStateILine();
1435 (void)tokenizer.lex();
1436 tokenizer.popState();
1437 break;
1439 tokenizer.pushState();
1440 tokenizer.setStateIFile();
1441 (void)tokenizer.lex();
1442 tokenizer.popState();
1443 break;
1444 default:
1445 return FALSE;
1446 }
1447 break;
1448 case TokenRetval::TK_HTMLTAG:
1449 {
1450 auto handleEnterLeaveStyle = [this,&parent,&children,&tokenName](DocStyleChange::Style style) {
1451 if (!context.token->endTag)
1452 {
1453 handleStyleEnter(parent,children,style,tokenName,&context.token->attribs);
1454 }
1455 else
1456 {
1457 handleStyleLeave(parent,children,style,tokenName);
1458 }
1459 };
1460 switch (Mappers::htmlTagMapper->map(tokenName))
1461 {
1463 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <div> tag in heading");
1464 break;
1466 warn_doc_error(context.fileName,tokenizer.getLineNr(),"found <pre> tag in heading");
1467 break;
1469 handleEnterLeaveStyle(DocStyleChange::Span);
1470 break;
1472 handleEnterLeaveStyle(DocStyleChange::Bold);
1473 break;
1475 handleEnterLeaveStyle(DocStyleChange::S);
1476 break;
1478 handleEnterLeaveStyle(DocStyleChange::Strike);
1479 break;
1481 handleEnterLeaveStyle(DocStyleChange::Del);
1482 break;
1484 handleEnterLeaveStyle(DocStyleChange::Underline);
1485 break;
1487 handleEnterLeaveStyle(DocStyleChange::Ins);
1488 break;
1490 case HtmlTagType::XML_C:
1491 handleEnterLeaveStyle(DocStyleChange::Code);
1492 break;
1494 handleEnterLeaveStyle(DocStyleChange::Kbd);
1495 break;
1497 handleEnterLeaveStyle(DocStyleChange::Italic);
1498 break;
1500 handleEnterLeaveStyle(DocStyleChange::Subscript);
1501 break;
1503 handleEnterLeaveStyle(DocStyleChange::Superscript);
1504 break;
1506 handleEnterLeaveStyle(DocStyleChange::Center);
1507 break;
1509 handleEnterLeaveStyle(DocStyleChange::Small);
1510 break;
1512 handleEnterLeaveStyle(DocStyleChange::Cite);
1513 break;
1515 if (!context.token->endTag)
1516 {
1517 handleImg(parent,children,context.token->attribs);
1518 }
1519 break;
1520 default:
1521 return FALSE;
1522 break;
1523 }
1524 }
1525 break;
1526 case TokenRetval::TK_SYMBOL:
1527 {
1530 {
1531 children.append<DocSymbol>(this,parent,s);
1532 }
1533 else
1534 {
1535 return FALSE;
1536 }
1537 }
1538 break;
1539 case TokenRetval::TK_WHITESPACE:
1540 case TokenRetval::TK_NEWPARA:
1541handlepara:
1542 if (insidePRE(parent) || !children.empty())
1543 {
1544 children.append<DocWhiteSpace>(this,parent,context.token->chars);
1545 }
1546 break;
1547 case TokenRetval::TK_LNKWORD:
1548 if (handleWord)
1549 {
1550 handleLinkedWord(parent,children);
1551 }
1552 else
1553 return FALSE;
1554 break;
1555 case TokenRetval::TK_WORD:
1556 if (handleWord)
1557 {
1558 children.append<DocWord>(this,parent,context.token->name);
1559 }
1560 else
1561 return FALSE;
1562 break;
1563 case TokenRetval::TK_URL:
1564 if (context.insideHtmlLink)
1565 {
1566 children.append<DocWord>(this,parent,context.token->name);
1567 }
1568 else
1569 {
1570 children.append<DocURL>(this,parent,context.token->name,context.token->isEMailAddr);
1571 }
1572 break;
1573 default:
1574 return FALSE;
1575 }
1576 return TRUE;
1577}
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:152
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:1393

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_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::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:638
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:126
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:3534
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:6335
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:3408

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:578
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:2822

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:1404
QCString convertNameToFile(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:4013

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

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

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

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

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

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

References DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, context, FALSE, findAndCopyImage(), found, 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:306
QCString tagName() const
Definition docnode.h:307
Style style() const
Definition docnode.h:302

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

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

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

References Definition::anchor(), DocNodeList::append(), AUTO_TRACE, AUTO_TRACE_ADD, Definition::briefDescriptionAsTooltip(), Config_getBool, 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 897 of file docparser.cpp.

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

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:305

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

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

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

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

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

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(), found, 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 1653 of file docparser.cpp.

1654{
1655 AUTO_TRACE("file={} text={}",file,text);
1656 bool ambig = false;
1657 QCString filePath = findFilePath(file,ambig);
1658 if (!filePath.isEmpty())
1659 {
1660 text = fileToString(filePath,Config_getBool(FILTER_SOURCE_FILES));
1661 if (ambig)
1662 {
1663 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file name '{}' is ambiguous"
1664 "Possible candidates:\n{}",file, showFileDefMatches(Doxygen::exampleNameLinkedMap,file));
1665 }
1666 }
1667 else
1668 {
1669 warn_doc_error(context.fileName,tokenizer.getLineNr(),"included file '{}' is not found. "
1670 "Check your EXAMPLE_PATH",file);
1671 }
1672}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:103
QCString findFilePath(const QCString &file, bool &ambig)
Definition util.cpp:3491
QCString fileToString(const QCString &name, bool filter, bool isSourceCode)
Definition util.cpp:1441

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 140 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(), and validatingParseText().

◆ contextStack

std::stack< DocParserContext > DocParser::contextStack

Definition at line 139 of file docparser_p.h.

Referenced by popContext(), and pushContext().

◆ tokenizer

DocTokenizer DocParser::tokenizer

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


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