summaryrefslogtreecommitdiffstats
path: root/src/util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.cpp')
-rw-r--r--src/util.cpp176
1 files changed, 103 insertions, 73 deletions
diff --git a/src/util.cpp b/src/util.cpp
index 5b799c8..aa1acb4 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -22,6 +22,8 @@
#include <cinttypes>
#include <string.h>
+#include <mutex>
+#include <unordered_set>
#include "md5.h"
@@ -276,22 +278,20 @@ QCString generateMarker(int id)
return result;
}
-static QCString stripFromPath(const QCString &path,QStrList &l)
+static QCString stripFromPath(const QCString &path,const StringVector &l)
{
// look at all the strings in the list and strip the longest match
- const char *s=l.first();
QCString potential;
unsigned int length = 0;
- while (s)
+ for (const auto &s : l)
{
- QCString prefix = s;
+ QCString prefix = s.c_str();
if (prefix.length() > length &&
qstricmp(path.left(prefix.length()),prefix)==0) // case insensitive compare
{
length = prefix.length();
potential = path.right(path.length()-prefix.length());
}
- s = l.next();
}
if (length) return potential;
return path;
@@ -1664,15 +1664,16 @@ static CharAroundSpace g_charAroundSpace;
// Note: this function is not reentrant due to the use of static buffer!
QCString removeRedundantWhiteSpace(const QCString &s)
{
- static bool cliSupport = Config_getBool(CPP_CLI_SUPPORT);
- static bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
+ bool cliSupport = Config_getBool(CPP_CLI_SUPPORT);
+ bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
if (s.isEmpty() || vhdl) return s;
// We use a static character array to
// improve the performance of this function
- static char *growBuf = 0;
- static int growBufLen = 0;
+ // and thread_local is needed to make it multi-thread safe
+ static THREAD_LOCAL char *growBuf = 0;
+ static THREAD_LOCAL int growBufLen = 0;
if ((int)s.length()*3>growBufLen) // For input character we produce at most 3 output characters,
{
growBufLen = s.length()*3;
@@ -2375,15 +2376,13 @@ int filterCRLF(char *buf,int len)
return dest; // length of the valid part of the buf
}
-static QCString getFilterFromList(const char *name,const QStrList &filterList,bool &found)
+static QCString getFilterFromList(const char *name,const StringVector &filterList,bool &found)
{
found=FALSE;
// compare the file name to the filter pattern list
- QStrListIterator sli(filterList);
- char* filterStr;
- for (sli.toFirst(); (filterStr = sli.current()); ++sli)
+ for (const auto &filterStr : filterList)
{
- QCString fs = filterStr;
+ QCString fs = filterStr.c_str();
int i_equals=fs.find('=');
if (i_equals!=-1)
{
@@ -2417,12 +2416,12 @@ QCString getFileFilter(const char* name,bool isSourceCode)
// sanity check
if (name==0) return "";
- QStrList& filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS);
- QStrList& filterList = Config_getList(FILTER_PATTERNS);
+ const StringVector& filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS);
+ const StringVector& filterList = Config_getList(FILTER_PATTERNS);
QCString filterName;
bool found=FALSE;
- if (isSourceCode && !filterSrcList.isEmpty())
+ if (isSourceCode && !filterSrcList.empty())
{ // first look for source filter pattern list
filterName = getFilterFromList(name,filterSrcList,found);
}
@@ -4480,11 +4479,19 @@ struct FindFileCacheElem
static QCache<FindFileCacheElem> g_findFileDefCache(5000);
+#if MULTITHREADED_INPUT
+static std::mutex g_findFileDefMutex;
+#endif
+
FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig)
{
ambig=FALSE;
if (n==0) return 0;
+#if MULTITHREADED_INPUT
+ std::unique_lock<std::mutex> lock(g_findFileDefMutex);
+#endif
+
const int maxAddrSize = 20;
char addr[maxAddrSize];
qsnprintf(addr,maxAddrSize,"%p:",(void*)fnMap);
@@ -4623,11 +4630,10 @@ QCString substituteKeywords(const QCString &s,const char *title,
int getPrefixIndex(const QCString &name)
{
if (name.isEmpty()) return 0;
- static QStrList &sl = Config_getList(IGNORE_PREFIX);
- char *s = sl.first();
- while (s)
+ const StringVector &sl = Config_getList(IGNORE_PREFIX);
+ for (const auto &s : sl)
{
- const char *ps=s;
+ const char *ps=s.c_str();
const char *pd=name.data();
int i=0;
while (*ps!=0 && *pd!=0 && *ps==*pd) ps++,pd++,i++;
@@ -4635,7 +4641,6 @@ int getPrefixIndex(const QCString &name)
{
return i;
}
- s = sl.next();
}
return 0;
}
@@ -5018,10 +5023,20 @@ void createSubDirs(QDir &d)
int l1,l2;
for (l1=0;l1<16;l1++)
{
- d.mkdir(QCString().sprintf("d%x",l1));
+ QCString subdir;
+ subdir.sprintf("d%x",l1);
+ if (!d.exists(subdir) && !d.mkdir(subdir))
+ {
+ term("Failed to create output directory '%s'\n",subdir.data());
+ }
for (l2=0;l2<256;l2++)
{
- d.mkdir(QCString().sprintf("d%x/d%02x",l1,l2));
+ QCString subsubdir;
+ subsubdir.sprintf("d%x/d%02x",l1,l2);
+ if (!d.exists(subsubdir) && !d.mkdir(subsubdir))
+ {
+ term("Failed to create output directory '%s'\n",subsubdir.data());
+ }
}
}
}
@@ -5268,6 +5283,16 @@ QCString convertToId(const char *s)
return growBuf.get();
}
+/*! Some strings have been corrected but the requirement regarding the fact
+ * that an id cannot have a digit at the first position. To overcome problems
+ * with double labels we always place an "a" in front
+ */
+QCString correctId(QCString s)
+{
+ if (s.isEmpty()) return s;
+ return "a" + s;
+}
+
/*! Converts a string to an XML-encoded string */
QCString convertToXML(const char *s, bool keepEntities)
{
@@ -6199,6 +6224,7 @@ void filterLatexString(FTextStream &t,const char *str,
case '%': t << "\\%"; break;
case '#': t << "\\#"; break;
case '$': t << "\\$"; break;
+ case '"': t << "\"{}"; break;
case '-': t << "-\\/"; break;
case '^': (usedTableLevels()>0) ? t << "\\string^" : t << (char)c; break;
case '~': t << "\\string~"; break;
@@ -6586,10 +6612,11 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine)
// search for leading empty lines
int i=0,li=-1,l=s.length();
char c;
- while ((c=*p++))
+ while ((c=*p))
{
- if (c==' ' || c=='\t' || c=='\r') i++;
- else if (c=='\n') i++,li=i,docLine++;
+ if (c==' ' || c=='\t' || c=='\r') i++,p++;
+ else if (c=='\\' && qstrncmp(p,"\\ilinebr",8)==0) i+=8,li=i,docLine++,p+=8;
+ else if (c=='\n') i++,li=i,docLine++,p++;
else break;
}
@@ -6598,9 +6625,10 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine)
p=s.data()+b;
while (b>=0)
{
- c=*p; p--;
- if (c==' ' || c=='\t' || c=='\r') b--;
- else if (c=='\n') bi=b,b--;
+ c=*p;
+ if (c==' ' || c=='\t' || c=='\r') b--,p--;
+ else if (c=='r' && b>=7 && qstrncmp(p-7,"\\ilinebr",8)==0) bi=b-7,b-=8,p-=8;
+ else if (c=='\n') bi=b,b--,p--;
else break;
}
@@ -6611,6 +6639,7 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine)
if (bi==-1) bi=l;
if (li==-1) li=0;
if (bi<=li) return 0; // only empty lines
+ //printf("docLine='%s' len=%d li=%d bi=%d\n",s.data(),s.length(),li,bi);
return s.mid(li,bi-li);
}
@@ -6962,7 +6991,8 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md,
if (doc.isEmpty()) return s.data();
FTextStream t(&s);
DocNode *root = validatingParseDoc(fileName,lineNr,
- (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE);
+ (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE,
+ 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
TextDocVisitor *visitor = new TextDocVisitor(t);
root->accept(visitor);
delete visitor;
@@ -6997,9 +7027,8 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md,
//--------------------------------------------------------------------------------------
-static QDict<void> aliasesProcessed;
-
-static QCString expandAliasRec(const QCString s,bool allowRecursion=FALSE);
+static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,
+ const QCString s,bool allowRecursion=FALSE);
struct Marker
{
@@ -7041,7 +7070,8 @@ static int findEndOfCommand(const char *s)
* with the corresponding values found in the comma separated argument
* list \a argList and the returns the result after recursive alias expansion.
*/
-static QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList)
+static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed,
+ const QCString &aliasValue,const QCString &argList)
{
//printf("----- replaceAliasArguments(val=[%s],args=[%s])\n",aliasValue.data(),argList.data());
@@ -7121,7 +7151,7 @@ static QCString replaceAliasArguments(const QCString &aliasValue,const QCString
//printf("part before marker %d: '%s'\n",i,aliasValue.mid(p,m->pos-p).data());
if (m->number>0 && m->number<=(int)args.count()) // valid number
{
- result+=expandAliasRec(*args.at(m->number-1),TRUE);
+ result+=expandAliasRec(aliasesProcessed,*args.at(m->number-1),TRUE);
//printf("marker index=%d pos=%d number=%d size=%d replacement %s\n",i,m->pos,m->number,m->size,
// args.at(m->number-1)->data());
}
@@ -7133,7 +7163,7 @@ static QCString replaceAliasArguments(const QCString &aliasValue,const QCString
// expand the result again
result = substitute(result,"\\{","{");
result = substitute(result,"\\}","}");
- result = expandAliasRec(substitute(result,"\\,",","));
+ result = expandAliasRec(aliasesProcessed,substitute(result,"\\,",","));
return result;
}
@@ -7160,7 +7190,7 @@ static QCString escapeCommas(const QCString &s)
return result.data();
}
-static QCString expandAliasRec(const QCString s,bool allowRecursion)
+static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCString s,bool allowRecursion)
{
QCString result;
static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*");
@@ -7193,19 +7223,20 @@ static QCString expandAliasRec(const QCString s,bool allowRecursion)
}
//printf("Found command s='%s' cmd='%s' numArgs=%d args='%s' aliasText=%s\n",
// s.data(),cmd.data(),numArgs,args.data(),aliasText?aliasText->data():"<none>");
- if ((allowRecursion || aliasesProcessed.find(cmd)==0) && aliasText) // expand the alias
+ if ((allowRecursion || aliasesProcessed.find(cmd.str())==aliasesProcessed.end()) &&
+ aliasText) // expand the alias
{
//printf("is an alias!\n");
- if (!allowRecursion) aliasesProcessed.insert(cmd,(void *)0x8);
+ if (!allowRecursion) aliasesProcessed.insert(cmd.str());
QCString val = *aliasText;
if (hasArgs)
{
- val = replaceAliasArguments(val,args);
+ val = replaceAliasArguments(aliasesProcessed,val,args);
//printf("replace '%s'->'%s' args='%s'\n",
// aliasText->data(),val.data(),args.data());
}
- result+=expandAliasRec(val);
- if (!allowRecursion) aliasesProcessed.remove(cmd);
+ result+=expandAliasRec(aliasesProcessed,val);
+ if (!allowRecursion) aliasesProcessed.erase(cmd.str());
p=i+l;
if (hasArgs) p+=argsLen+2;
}
@@ -7275,9 +7306,9 @@ QCString extractAliasArgs(const QCString &args,int pos)
QCString resolveAliasCmd(const QCString aliasCmd)
{
QCString result;
- aliasesProcessed.clear();
+ StringUnorderedSet aliasesProcessed;
//printf("Expanding: '%s'\n",aliasCmd.data());
- result = expandAliasRec(aliasCmd);
+ result = expandAliasRec(aliasesProcessed,aliasCmd);
//printf("Expanding result: '%s'->'%s'\n",aliasCmd.data(),result.data());
return result;
}
@@ -7285,12 +7316,12 @@ QCString resolveAliasCmd(const QCString aliasCmd)
QCString expandAlias(const QCString &aliasName,const QCString &aliasValue)
{
QCString result;
- aliasesProcessed.clear();
+ StringUnorderedSet aliasesProcessed;
// avoid expanding this command recursively
- aliasesProcessed.insert(aliasName,(void *)0x8);
+ aliasesProcessed.insert(aliasName.str());
// expand embedded commands
//printf("Expanding: '%s'->'%s'\n",aliasName.data(),aliasValue.data());
- result = expandAliasRec(aliasValue);
+ result = expandAliasRec(aliasesProcessed,aliasValue);
//printf("Expanding result: '%s'->'%s'\n",aliasName.data(),result.data());
return result;
}
@@ -7308,7 +7339,8 @@ void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList
linkifyText(TextGeneratorOLImpl(ol),d,0,0,a.type);
ol.endConstraintType();
ol.startConstraintDocs();
- ol.generateDoc(d->docFile(),d->docLine(),d,0,a.docs,TRUE,FALSE);
+ ol.generateDoc(d->docFile(),d->docLine(),d,0,a.docs,TRUE,FALSE,
+ 0,FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
ol.endConstraintDocs();
}
ol.endConstraintList();
@@ -7495,9 +7527,9 @@ QCString filterTitle(const QCString &title)
// returns TRUE if the name of the file represented by 'fi' matches
// one of the file patterns in the 'patList' list.
-bool patternMatch(const QFileInfo &fi,const QStrList *patList)
+bool patternMatch(const QFileInfo &fi,const StringVector &patList)
{
- static bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES);
+ bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES);
bool found = FALSE;
// For platforms where the file system is non case sensitive overrule the setting
@@ -7506,17 +7538,15 @@ bool patternMatch(const QFileInfo &fi,const QStrList *patList)
caseSenseNames = FALSE;
}
- if (patList)
+ if (!patList.empty())
{
- QStrListIterator it(*patList);
- QCString pattern;
-
QCString fn = fi.fileName().data();
QCString fp = fi.filePath().data();
QCString afp= fi.absFilePath().data();
- for (it.toFirst();(pattern=it.current());++it)
+ for (const auto &pat: patList)
{
+ QCString pattern = pat.c_str();
if (!pattern.isEmpty())
{
int i=pattern.find('=');
@@ -8107,20 +8137,22 @@ bool classVisibleInIndex(const ClassDef *cd)
QCString extractDirection(QCString &docs)
{
- QRegExp re("\\[[^\\]]+\\]"); // [...]
+ QRegExp re("\\[[ inout,]+\\]"); // [...]
int l=0;
- if (re.match(docs,0,&l)==0)
+ if (re.match(docs,0,&l)==0 && l>2)
{
- int inPos = docs.find("in", 1,FALSE);
- int outPos = docs.find("out",1,FALSE);
- bool input = inPos!=-1 && inPos<l;
- bool output = outPos!=-1 && outPos<l;
- if (input || output) // in,out attributes
+ // make dir the part inside [...] without separators
+ QCString dir=substitute(substitute(docs.mid(1,l-2)," ",""),",","");
+ int inIndex, outIndex;
+ unsigned char ioMask=0;
+ if (( inIndex=dir.find( "in"))!=-1) dir.remove (inIndex,2),ioMask|=(1<<0);
+ if ((outIndex=dir.find("out"))!=-1) dir.remove(outIndex,3),ioMask|=(1<<1);
+ if (dir.isEmpty() && ioMask!=0) // only in and/or out attributes found
{
docs = docs.mid(l); // strip attributes
- if (input && output) return "[in,out]";
- else if (input) return "[in]";
- else if (output) return "[out]";
+ if (ioMask==((1<<0)|(1<<1))) return "[in,out]";
+ else if (ioMask==(1<<0)) return "[in]";
+ else if (ioMask==(1<<1)) return "[out]";
}
}
return QCString();
@@ -8357,18 +8389,16 @@ bool openOutputFile(const char *outFile,QFile &f)
void writeExtraLatexPackages(FTextStream &t)
{
// User-specified packages
- QStrList &extraPackages = Config_getList(EXTRA_PACKAGES);
- if (!extraPackages.isEmpty())
+ const StringVector &extraPackages = Config_getList(EXTRA_PACKAGES);
+ if (!extraPackages.empty())
{
t << "% Packages requested by user\n";
- const char *pkgName=extraPackages.first();
- while (pkgName)
+ for (const auto &pkgName : extraPackages)
{
if ((pkgName[0] == '[') || (pkgName[0] == '{'))
- t << "\\usepackage" << pkgName << "\n";
+ t << "\\usepackage" << pkgName.c_str() << "\n";
else
- t << "\\usepackage{" << pkgName << "}\n";
- pkgName=extraPackages.next();
+ t << "\\usepackage{" << pkgName.c_str() << "}\n";
}
t << "\n";
}