summaryrefslogtreecommitdiff
path: root/src/util.cpp
diff options
context:
space:
mode:
authorTizenOpenSource <tizenopensrc@samsung.com>2022-12-27 15:39:10 +0900
committerTizenOpenSource <tizenopensrc@samsung.com>2022-12-27 15:39:10 +0900
commitcfd886868fa8595b045007a2ad673c18c5f222b3 (patch)
tree5d1b3cd3c098c0e5238e4a6a9be351a67f2d6bc1 /src/util.cpp
parent9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00 (diff)
downloaddoxygen-cfd886868fa8595b045007a2ad673c18c5f222b3.tar.gz
doxygen-cfd886868fa8595b045007a2ad673c18c5f222b3.tar.bz2
doxygen-cfd886868fa8595b045007a2ad673c18c5f222b3.zip
Imported Upstream version 1.9.5upstream/1.9.5
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp410
1 files changed, 265 insertions, 145 deletions
diff --git a/src/util.cpp b/src/util.cpp
index f957181..12d13eb 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -73,6 +73,8 @@
#include "dir.h"
#include "utf8.h"
#include "textstream.h"
+#include "indexlist.h"
+#include "datetime.h"
#define ENABLE_TRACINGSUPPORT 0
@@ -331,33 +333,31 @@ QCString stripFromIncludePath(const QCString &path)
int guessSection(const QCString &name)
{
QCString n=name.lower();
- if (n.right(2)==".c" || // source
- n.right(3)==".cc" ||
- n.right(4)==".cxx" ||
- n.right(4)==".cpp" ||
- n.right(4)==".c++" ||
- n.right(5)==".java" ||
- n.right(2)==".m" ||
- n.right(3)==".mm" ||
- n.right(3)==".ii" || // inline
- n.right(4)==".ixx" ||
- n.right(4)==".ipp" ||
- n.right(4)==".i++" ||
- n.right(4)==".inl" ||
- n.right(4)==".xml" ||
- n.right(4)==".lex" ||
- n.right(4)==".sql"
- ) return Entry::SOURCE_SEC;
- if (n.right(2)==".h" || // header
- n.right(3)==".hh" ||
- n.right(4)==".hxx" ||
- n.right(4)==".hpp" ||
- n.right(4)==".h++" ||
- n.right(4)==".idl" ||
- n.right(4)==".ddl" ||
- n.right(5)==".pidl" ||
- n.right(4)==".ice"
- ) return Entry::HEADER_SEC;
+ static const std::unordered_set<std::string> sourceExt = {
+ "c","cc","cxx","cpp","c++", // C/C++
+ "java", // Java
+ "cs", // C#
+ "m","mm", // Objective-C
+ "ii","ixx","ipp","i++","inl", // C/C++ inline
+ "xml","lex","sql" // others
+ };
+ static const std::unordered_set<std::string> headerExt = {
+ "h", "hh", "hxx", "hpp", "h++" // C/C++ header
+ "idl", "ddl", "pidl", "ice" // IDL like
+ };
+ int lastDot = n.findRev('.');
+ if (lastDot!=-1)
+ {
+ QCString extension = n.mid(lastDot+1); // part after the last dot
+ if (sourceExt.find(extension.str())!=sourceExt.end())
+ {
+ return Entry::SOURCE_SEC;
+ }
+ if (headerExt.find(extension.str())!=headerExt.end())
+ {
+ return Entry::HEADER_SEC;
+ }
+ }
return 0;
}
@@ -488,12 +488,6 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName,
}
-int computeQualifiedIndex(const QCString &name)
-{
- int i = name.find('<');
- return name.findRev("::",i==-1 ? name.length() : i);
-}
-
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
@@ -896,7 +890,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
size_t strLen = txtStr.length();
if (strLen==0) return;
- static const reg::Ex regExp(R"((::)?\a[\w~!\\.:$]*)");
+ static const reg::Ex regExp(R"((::)?\a[\w~!\\.:$"]*)");
reg::Iterator it(txtStr,regExp);
reg::Iterator end;
@@ -926,6 +920,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
for (size_t i=index;i<newIndex;i++)
{
if (txtStr.at(i)=='"') insideString=!insideString;
+ if (txtStr.at(i)=='\\') i++; // skip next character it is escaped
}
//printf("floatingIndex=%d strlen=%d autoBreak=%d\n",floatingIndex,strLen,autoBreak);
@@ -1067,7 +1062,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
if (md!=self && (self==0 || md->name()!=self->name()))
// name check is needed for overloaded members, where getDefs just returns one
{
- /* in case of Fortran scop and the variable is a non Fortran variable: don't link,
+ /* in case of Fortran scope and the variable is a non Fortran variable: don't link,
* see also getLink in fortrancode.l
*/
if (!(scope && (scope->getLanguage() == SrcLangExt_Fortran) && md->isVariable() && (md->getLanguage() != SrcLangExt_Fortran)))
@@ -1339,20 +1334,18 @@ QCString getFileFilter(const QCString &name,bool isSourceCode)
else
{
/* remove surrounding double quotes */
- if ((filterName.right(1) == "\"") && (filterName.left(1) == "\""))
+ if (filterName.length()>=2 && filterName[0]=='"' && filterName[filterName.length()-1]=='"')
{
- filterName.remove(filterName.length() - 1, 1);
- filterName.remove(0, 1);
+ filterName = filterName.mid(1,filterName.length()-2);
}
return filterName;
}
}
-QCString transcodeCharacterStringToUTF8(const QCString &input)
+QCString transcodeCharacterStringToUTF8(const QCString &inputEncoding, const QCString &input)
{
bool error=FALSE;
- QCString inputEncoding = Config_getString(INPUT_ENCODING);
const char *outputEncoding = "UTF-8";
if (inputEncoding.isEmpty() || qstricmp(inputEncoding,outputEncoding)==0) return input;
int inputSize=input.length();
@@ -1384,8 +1377,8 @@ QCString transcodeCharacterStringToUTF8(const QCString &input)
qPrint(inputEncoding),outputEncoding,qPrint(input));
error=TRUE;
}
+ portable_iconv_close(cd);
}
- portable_iconv_close(cd);
return error ? input : output;
}
@@ -1435,58 +1428,6 @@ QCString fileToString(const QCString &name,bool filter,bool isSourceCode)
return "";
}
-static std::tm getCurrentDateTime()
-{
- QCString sourceDateEpoch = Portable::getenv("SOURCE_DATE_EPOCH");
- if (!sourceDateEpoch.isEmpty()) // see https://reproducible-builds.org/specs/source-date-epoch/
- {
- bool ok;
- uint64 epoch = sourceDateEpoch.toUInt64(&ok);
- if (!ok)
- {
- static bool warnedOnce=FALSE;
- if (!warnedOnce)
- {
- warn_uncond("Environment variable SOURCE_DATE_EPOCH does not contain a valid number; value is '%s'\n",
- qPrint(sourceDateEpoch));
- warnedOnce=TRUE;
- }
- }
- else // use given epoch value as current 'built' time
- {
- auto epoch_start = std::chrono::time_point<std::chrono::system_clock>{};
- auto epoch_seconds = std::chrono::seconds(epoch);
- auto build_time = epoch_start + epoch_seconds;
- std::time_t time = std::chrono::system_clock::to_time_t(build_time);
- return *gmtime(&time);
- }
- }
-
- // return current local time
- auto now = std::chrono::system_clock::now();
- std::time_t time = std::chrono::system_clock::to_time_t(now);
- return *localtime(&time);
-}
-
-QCString dateToString(bool includeTime)
-{
- auto current = getCurrentDateTime();
- return theTranslator->trDateTime(current.tm_year + 1900,
- current.tm_mon + 1,
- current.tm_mday,
- (current.tm_wday+6)%7+1, // map: Sun=0..Sat=6 to Mon=1..Sun=7
- current.tm_hour,
- current.tm_min,
- current.tm_sec,
- includeTime);
-}
-
-QCString yearToString()
-{
- auto current = getCurrentDateTime();
- return QCString().setNum(current.tm_year+1900);
-}
-
void trimBaseClassScope(const BaseClassList &bcl,QCString &s,int level=0)
{
//printf("trimBaseClassScope level=%d '%s'\n",level,qPrint(s));
@@ -2143,6 +2084,8 @@ void mergeArguments(ArgumentList &srcAl,ArgumentList &dstAl,bool forceNameOverwr
}
}
+//---------------------------------------------------------------------------------------
+
static void findMembersWithSpecificName(const MemberName *mn,
const QCString &args,
bool checkStatics,
@@ -2185,6 +2128,51 @@ static void findMembersWithSpecificName(const MemberName *mn,
}
}
+//---------------------------------------------------------------------------------------
+
+bool getDefsNew(const QCString &scName,
+ const QCString &mbName,
+ const QCString &args,
+ const MemberDef *&md,
+ const ClassDef *&cd,
+ const FileDef *&fd,
+ const NamespaceDef *&nd,
+ const GroupDef *&gd,
+ bool forceEmptyScope,
+ const FileDef *currentFile,
+ bool checkCV
+ )
+{
+ fd=0, md=0, cd=0, nd=0, gd=0;
+ if (mbName.isEmpty()) return false;
+
+ //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
+ const Definition *scope = Doxygen::globalScope;
+ SymbolResolver resolver;
+ if (currentFile) resolver.setFileScope(currentFile);
+ if (!scName.isEmpty())
+ {
+ scope = resolver.resolveSymbol(scope,scName);
+ }
+ if (scope==Doxygen::globalScope)
+ {
+ scope = currentFile;
+ }
+ //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(scName),qPrint(mbName),qPrint(scope?scope->name():""));
+ //
+ const Definition *symbol = resolver.resolveSymbol(scope,mbName,args,checkCV);
+ //printf("@@ -> found symbol in=%s out=%s\n",qPrint(mbName),qPrint(symbol?symbol->qualifiedName():QCString()));
+ if (symbol && symbol->definitionType()==Definition::TypeMember)
+ {
+ md = toMemberDef(symbol);
+ cd = md->getClassDef();
+ if (cd==0) nd = md->getNamespaceDef();
+ if (cd==0 && nd==0) fd = md->getFileDef();
+ gd = md->getGroupDef();
+ }
+ return md!=0;
+}
+
/*!
* Searches for a member definition given its name 'memberName' as a string.
* memberName may also include a (partial) scope to indicate the scope
@@ -2207,7 +2195,7 @@ static void findMembersWithSpecificName(const MemberName *mn,
* - if 'fd' is non zero, the member was found in the global namespace of
* file fd.
*/
-bool getDefs(const QCString &scName,
+bool getDefsOld(const QCString &scName,
const QCString &mbName,
const QCString &args,
const MemberDef *&md,
@@ -2221,16 +2209,23 @@ bool getDefs(const QCString &scName,
)
{
fd=0, md=0, cd=0, nd=0, gd=0;
- if (mbName.isEmpty()) return FALSE; /* empty name => nothing to link */
+ bool result = FALSE;
+ QCString scopeName;
+ QCString memberName;
+ QCString mName;
+ QCString mScope;
+ MemberName *mn = 0;
+ int is,im=0,pm=0;
+
+ if (mbName.isEmpty()) goto exit; /* empty name => nothing to link */
- QCString scopeName=scName;
- QCString memberName=mbName;
- scopeName = substitute(scopeName,"\\","::"); // for PHP
+ scopeName = scName;
+ scopeName = substitute(scopeName,"\\","::"); // for PHP
+ memberName = mbName;
memberName = substitute(memberName,"\\","::"); // for PHP
//printf("Search for name=%s args=%s in scope=%s forceEmpty=%d\n",
// qPrint(memberName),qPrint(args),qPrint(scopeName),forceEmptyScope);
- int is,im=0,pm=0;
// strip common part of the scope from the scopeName
while ((is=scopeName.findRev("::"))!=-1 &&
(im=memberName.find("::",pm))!=-1 &&
@@ -2243,9 +2238,8 @@ bool getDefs(const QCString &scName,
//printf("result after scope corrections scope=%s name=%s\n",
// qPrint(scopeName), qPrint(memberName));
- QCString mName=memberName;
- QCString mScope;
- if (memberName.left(9)!="operator " && // treat operator conversion methods
+ mName=memberName;
+ if (!memberName.startsWith("operator ") && // treat operator conversion methods
// as a special case
(im=memberName.findRev("::"))!=-1 &&
im<static_cast<int>(memberName.length())-2 // not A::
@@ -2260,7 +2254,7 @@ bool getDefs(const QCString &scName,
//printf("mScope='%s' mName='%s'\n",qPrint(mScope),qPrint(mName));
- MemberName *mn = Doxygen::memberNameLinkedMap->find(mName);
+ mn = Doxygen::memberNameLinkedMap->find(mName);
//printf("mName=%s mn=%p\n",qPrint(mName),mn);
if ((!forceEmptyScope || scopeName.isEmpty()) && // this was changed for bug638856, forceEmptyScope => empty scopeName
@@ -2362,13 +2356,15 @@ bool getDefs(const QCString &scName,
{
md=0; // avoid returning things we cannot link to
cd=0;
- return FALSE; // match found, but was not linkable
+ result=FALSE; // match found, but was not linkable
+ goto exit;
}
else
{
gd=md->getGroupDef();
if (gd) cd=0;
- return TRUE; /* found match */
+ result=TRUE; /* found match */
+ goto exit;
}
}
}
@@ -2383,13 +2379,15 @@ bool getDefs(const QCString &scName,
{
cd=tmd->getClassDef();
md=emd;
- return TRUE;
+ result=TRUE;
+ goto exit;
}
else
{
cd=0;
md=0;
- return FALSE;
+ result=FALSE;
+ goto exit;
}
}
}
@@ -2453,7 +2451,8 @@ bool getDefs(const QCString &scName,
{
md = fuzzy_mmd;
cd = fuzzy_mmd->getClassDef();
- return TRUE;
+ result=TRUE;
+ goto exit;
}
}
@@ -2508,7 +2507,8 @@ bool getDefs(const QCString &scName,
{
md=0;
cd=0;
- return FALSE;
+ result=FALSE;
+ goto exit;
}
}
else if (mmd->getOuterScope()==fnd /* && mmd->isLinkable() */ )
@@ -2554,13 +2554,15 @@ bool getDefs(const QCString &scName,
{
md=0; // avoid returning things we cannot link to
nd=0;
- return FALSE; // match found but not linkable
+ result=FALSE; // match found but not linkable
+ goto exit;
}
else
{
gd=md->resolveAlias()->getGroupDef();
if (gd && gd->isLinkable()) nd=0; else gd=0;
- return TRUE;
+ result=TRUE;
+ goto exit;
}
}
}
@@ -2588,7 +2590,8 @@ bool getDefs(const QCString &scName,
if (gd && gd->isLinkable()) fd=0; else gd=0;
//printf("Found scoped enum %s fd=%p gd=%p\n",
// qPrint(mmd->name()),fd,gd);
- return TRUE;
+ result=TRUE;
+ goto exit;
}
}
}
@@ -2668,15 +2671,84 @@ bool getDefs(const QCString &scName,
gd=md->getGroupDef();
//printf("fd=%p gd=%p gd->isLinkable()=%d\n",fd,gd,gd->isLinkable());
if (gd && gd->isLinkable()) fd=0; else gd=0;
- return TRUE;
+ result=TRUE;
+ goto exit;
}
}
}
- // no nothing found
- return FALSE;
+exit:
+ return result;
+}
+
+bool getDefs(const QCString &scName,
+ const QCString &mbName,
+ const QCString &args,
+ const MemberDef *&md,
+ const ClassDef *&cd,
+ const FileDef *&fd,
+ const NamespaceDef *&nd,
+ const GroupDef *&gd,
+ bool forceEmptyScope,
+ const FileDef *currentFile,
+ bool checkCV
+ )
+{
+ if (false) // set this to true to try the old and new routine side-by-side and compare the results
+ {
+ printf("@@ ------ getDefsOld start\n");
+ bool result = getDefsOld(scName,mbName,args,md,cd,fd,nd,gd,forceEmptyScope,currentFile,checkCV);
+ printf("@@ ------ getDefsOld end\n");
+ const MemberDef *nmd = 0;
+ const ClassDef *ncd = 0;
+ const FileDef *nfd = 0;
+ const NamespaceDef *nnd = 0;
+ const GroupDef *ngd = 0;
+ printf("@@ ------ getDefsNew start\n");
+ bool newResult = getDefsNew(scName,mbName,args,
+ nmd,ncd,nfd,nnd,ngd,
+ forceEmptyScope,currentFile,checkCV);
+ printf("@@ ------ getDefsNew end\n");
+ if (result!=newResult || nmd!=md || ncd!=cd || nfd!=fd || nnd!=nd || ngd!=gd)
+ {
+ printf("@@ getDefsOld(scName=%s, mbName=%s, args=%s, forceEmptyScope=%d "
+ "currentFile=%s checkCV=%d)=%d md=%s (%p) cd=%s fd=%s nd=%s gd=%s\n",
+ qPrint(scName), qPrint(mbName), qPrint(args),
+ forceEmptyScope, qPrint(currentFile?currentFile->name():QCString()),
+ checkCV,
+ result,
+ qPrint(md?md->name():QCString()),
+ (void*)md,
+ qPrint(cd?cd->name():QCString()),
+ qPrint(fd?fd->name():QCString()),
+ qPrint(nd?nd->name():QCString()),
+ qPrint(gd?gd->name():QCString())
+ );
+ printf("@@ ------ getDefsOld start\n");
+ printf("@@ getDefsNew(scName=%s, mbName=%s, args=%s, forceEmptyScope=%d "
+ "currentFile=%s checkCV=%d)=%d md=%s (%p) cd=%s fd=%s nd=%s gd=%s\n",
+ qPrint(scName), qPrint(mbName), qPrint(args),
+ forceEmptyScope, qPrint(currentFile?currentFile->name():QCString()),
+ checkCV,
+ newResult,
+ qPrint(nmd?nmd->name():QCString()),
+ (void*)nmd,
+ qPrint(ncd?ncd->name():QCString()),
+ qPrint(nfd?nfd->name():QCString()),
+ qPrint(nnd?nnd->name():QCString()),
+ qPrint(ngd?ngd->name():QCString())
+ );
+ }
+ return result; // use return newResult to use the result of the new routine
+ }
+ else // do one of the two getDefs routines (comment out the other one)
+ {
+ return getDefsNew(scName,mbName,args,md,cd,fd,nd,gd,forceEmptyScope,currentFile,checkCV);
+ //return getDefsOld(scName,mbName,args,md,cd,fd,nd,gd,forceEmptyScope,currentFile,checkCV);
+ }
}
+
/*!
* Searches for a scope definition given its name as a string via parameter
* `scope`.
@@ -2780,10 +2852,10 @@ bool resolveRef(/* in */ const QCString &scName,
int bracePos=findParameterList(fullName);
int endNamePos=bracePos!=-1 ? bracePos : fullName.length();
int scopePos=fullName.findRev("::",endNamePos);
- bool explicitScope = fullName.left(2)=="::" && // ::scope or #scope
- (scopePos>2 || // ::N::A
- tsName.left(2)=="::" || // ::foo in local scope
- scName==0 // #foo in global scope
+ bool explicitScope = fullName.startsWith("::") && // ::scope or #scope
+ (scopePos>2 || // ::N::A
+ tsName.startsWith("::") || // ::foo in local scope
+ scName==0 // #foo in global scope
);
// default result values
@@ -3346,6 +3418,7 @@ QCString substituteKeywords(const QCString &s,const QCString &title,
result = substitute(result,"$projectnumber",projNum);
result = substitute(result,"$projectbrief",projBrief);
result = substitute(result,"$projectlogo",stripPath(Config_getString(PROJECT_LOGO)));
+ result = substitute(result,"$langISO",theTranslator->trISOLang());
return result;
}
@@ -3439,11 +3512,20 @@ int getUtf8Char(const char *input,char ids[MAX_UTF8_CHAR_SIZE],CaseModifier modi
}
#endif
+bool getCaseSenseNames()
+{
+ auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
+
+ if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
+ else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
+ else return Portable::fileSystemIsCaseSensitive();
+}
+
// note that this function is not reentrant due to the use of static growBuf!
QCString escapeCharsInString(const QCString &name,bool allowDots,bool allowUnderscore)
{
if (name.isEmpty()) return name;
- bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES);
+ bool caseSenseNames = getCaseSenseNames();
bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES);
GrowBuf growBuf;
signed char c;
@@ -3525,7 +3607,7 @@ QCString escapeCharsInString(const QCString &name,bool allowDots,bool allowUnder
QCString unescapeCharsInString(const QCString &s)
{
if (s.isEmpty()) return s;
- bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES);
+ bool caseSenseNames = getCaseSenseNames();
QCString result;
const char *p = s.data();
if (p)
@@ -3779,7 +3861,7 @@ done:
}
//printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
// qPrint(className),qPrint(namespaceName));
- if (/*className.right(2)=="-g" ||*/ className.right(2)=="-p")
+ if (className.endsWith("-p"))
{
className = className.left(className.length()-2);
}
@@ -4358,7 +4440,7 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri
if (lang == SrcLangExt_Fortran)
{
if (type[pos]==',') return -1;
- if (QCString(type).left(4).lower()!="type")
+ if (!type.lower().startsWith("type"))
{
re = &re_fortran;
}
@@ -4525,17 +4607,17 @@ QCString substituteTemplateArgumentsInString(
{
actArg = *actIt;
}
- if (formArg.type.left(6)=="class " && formArg.name.isEmpty())
+ if (formArg.type.startsWith("class ") && formArg.name.isEmpty())
{
formArg.name = formArg.type.mid(6);
formArg.type = "class";
}
- if (formArg.type.left(9)=="typename " && formArg.name.isEmpty())
+ if (formArg.type.startsWith("typename ") && formArg.name.isEmpty())
{
formArg.name = formArg.type.mid(9);
formArg.type = "typename";
}
- if (formArg.type=="class" || formArg.type=="typename" || formArg.type.left(8)=="template")
+ if (formArg.type=="class" || formArg.type=="typename" || formArg.type.startsWith("template"))
{
//printf("n=%s formArg->type='%s' formArg->name='%s' formArg->defval='%s'\n",
// qPrint(n),qPrint(formArg->type),qPrint(formArg->name),qPrint(formArg->defval));
@@ -4797,7 +4879,7 @@ PageDef *addRelatedPage(const QCString &name,const QCString &ptitle,
if (newPage) // new page
{
QCString baseName=name;
- if (baseName.right(4)==".tex")
+ if (baseName.endsWith(".tex"))
baseName=baseName.left(baseName.length()-4);
else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension)
baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
@@ -5656,8 +5738,8 @@ static MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fil
if (name.isEmpty())
return 0; // no name was given
- auto range = Doxygen::symbolMap->find(name);
- if (range.first==range.second)
+ auto &range = Doxygen::symbolMap->find(name);
+ if (range.empty())
return 0; // could not find any matching symbols
// mostly copied from getResolvedClassRec()
@@ -5674,9 +5756,8 @@ static MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fil
int minDistance = 10000;
MemberDef *bestMatch = 0;
- for (auto it=range.first; it!=range.second; ++it)
+ for (Definition *d : range)
{
- Definition *d = it->second;
if (d->definitionType()==Definition::TypeMember)
{
SymbolResolver resolver(fileScope);
@@ -5949,7 +6030,7 @@ static QCString escapeCommas(const QCString &s)
static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCString &s,bool allowRecursion)
{
QCString result;
- static const reg::Ex re(R"([\\@](\a\w*))");
+ static const reg::Ex re(R"([\\@](\a[\w-]*))");
std::string str = s.str();
reg::Match match;
size_t p = 0;
@@ -6010,6 +6091,13 @@ static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCStri
result+=s.right(s.length()-p);
//printf("expandAliases '%s'->'%s'\n",s.data(),result.data());
+ if (result == s)
+ {
+ std::string orgStr = s.str();
+ int ridx = orgStr.rfind('-');
+ if (ridx != -1) return expandAliasRec(aliasesProcessed,s.left(ridx),allowRecursion) + s.right(s.length() - ridx);
+ }
+
return result;
}
@@ -6250,7 +6338,7 @@ bool readInputFile(const QCString &fileName,BufStr &inBuf,bool filter,bool isSou
{
// do character transcoding if needed.
transcodeCharacterBuffer(fileName,inBuf,inBuf.curPos(),
- Config_getString(INPUT_ENCODING),"UTF-8");
+ getEncoding(fi),"UTF-8");
}
//inBuf.addChar('\n'); /* to prevent problems under Windows ? */
@@ -6290,13 +6378,15 @@ QCString filterTitle(const QCString &title)
return QCString(tf);
}
-//----------------------------------------------------------------------------
-// returns TRUE if the name of the file represented by 'fi' matches
-// one of the file patterns in the 'patList' list.
+//---------------------------------------------------------------------------------------------------
-bool patternMatch(const FileInfo &fi,const StringVector &patList)
+template<class PatternList, class PatternElem, typename PatternGet = QCString(*)(const PatternElem &)>
+bool genericPatternMatch(const FileInfo &fi,
+ const PatternList &patList,
+ PatternElem &elem,
+ PatternGet getter)
{
- bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES);
+ bool caseSenseNames = getCaseSenseNames();
bool found = FALSE;
// For platforms where the file system is non case sensitive overrule the setting
@@ -6311,8 +6401,9 @@ bool patternMatch(const FileInfo &fi,const StringVector &patList)
std::string fp = fi.filePath();
std::string afp= fi.absFilePath();
- for (auto pattern: patList)
+ for (const auto &li : patList)
{
+ std::string pattern = getter(li).str();
if (!pattern.empty())
{
size_t i=pattern.find('=');
@@ -6329,7 +6420,11 @@ bool patternMatch(const FileInfo &fi,const StringVector &patList)
found = re.isValid() && (reg::match(fn,re) ||
(fn!=fp && reg::match(fp,re)) ||
(fn!=afp && fp!=afp && reg::match(afp,re)));
- if (found) break;
+ if (found)
+ {
+ elem = li;
+ break;
+ }
//printf("Matching '%s' against pattern '%s' found=%d\n",
// qPrint(fi->fileName()),qPrint(pattern),found);
}
@@ -6338,6 +6433,31 @@ bool patternMatch(const FileInfo &fi,const StringVector &patList)
return found;
}
+//----------------------------------------------------------------------------
+// returns TRUE if the name of the file represented by 'fi' matches
+// one of the file patterns in the 'patList' list.
+
+bool patternMatch(const FileInfo &fi,const StringVector &patList)
+{
+ std::string elem;
+ auto getter = [](std::string s) { return QCString(s); };
+ return genericPatternMatch(fi,patList,elem,getter);
+}
+
+QCString getEncoding(const FileInfo &fi)
+{
+ InputFileEncoding elem;
+ auto getter = [](const InputFileEncoding &e) { return e.pattern; };
+ if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
+ {
+ return elem.encoding;
+ }
+ else // fall back to default encoding
+ {
+ return Config_getString(INPUT_ENCODING);
+ }
+}
+
QCString externalLinkTarget(const bool parent)
{
bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
@@ -6578,12 +6698,12 @@ QCString getLanguageSpecificSeparator(SrcLangExt lang,bool classScope)
/** Checks whether the given url starts with a supported protocol */
bool isURL(const QCString &url)
{
+ static const std::unordered_set<std::string> schemes = {
+ "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
+ };
QCString loc_url = url.stripWhiteSpace();
- return loc_url.left(5)=="http:" || loc_url.left(6)=="https:" ||
- loc_url.left(4)=="ftp:" || loc_url.left(5)=="ftps:" ||
- loc_url.left(5)=="sftp:" || loc_url.left(5)=="file:" ||
- loc_url.left(5)=="news:" || loc_url.left(4)=="irc:" ||
- loc_url.left(5)=="ircs:";
+ int colonPos = loc_url.find(':');
+ return colonPos!=-1 && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
}
/** Corrects URL \a url according to the relative path \a relPath.
* Returns the corrected URL. For absolute URLs no correction will be done.