Blob Blame History Raw
commit f3ebc866c88b31ab393637e30189d41ddb7f84f0
Author: Dimitri van Heesch <doxygen@gmail.com>
Date:   Fri Apr 17 21:39:13 2020 +0200

    issue #7706: Md5 hash does not match for two different runs

diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index 8a76a1d7..b5377a49 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
- * 
+ *
  *
  * Copyright (C) 1997-2015 by Dimitri van Heesch.
  *
  * Permission to use, copy, modify, and distribute this software and its
- * documentation under the terms of the GNU General Public License is hereby 
- * granted. No representations are made about the suitability of this software 
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
  * for any purpose. It is provided "as is" without express or implied warranty.
  * See the GNU General Public License for more details.
  *
@@ -63,10 +63,11 @@ MemberList::~MemberList()
   delete memberGroupList;
 }
 
-int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
+static int genericCompareMembers(const MemberDef *c1,const MemberDef *c2)
 {
-  static bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST);
-  if (sortConstructorsFirst) {
+  bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST);
+  if (sortConstructorsFirst)
+  {
     int ord1 = c1->isConstructor() ? 2 : (c1->isDestructor() ? 1 : 0);
     int ord2 = c2->isConstructor() ? 2 : (c2->isDestructor() ? 1 : 0);
     if (ord1 > ord2)
@@ -74,11 +75,19 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
     else if (ord2 > ord1)
       return 1;
   }
+  // sort on name
   int cmp = qstricmp(c1->name(),c2->name());
+  // then on argument list
   if (cmp==0 && c1->argsString() && c2->argsString())
   {
     cmp = qstricmp(c1->argsString(),c2->argsString());
   }
+  // then on file in which the item is defined
+  if (cmp==0)
+  {
+    cmp = qstricmp(c1->getDefFileName(),c2->getDefFileName());
+  }
+  // then on line number at which the member is defined
   if (cmp==0)
   {
     cmp = c1->getDefLine()-c2->getDefLine();
@@ -86,6 +95,11 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
   return cmp;
 }
 
+int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
+{
+  return genericCompareMembers(c1,c2);
+}
+
 int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const
 {
   int count=0;
@@ -295,7 +309,7 @@ MemberDef *MemberList::take(uint index)
 }
 
 MemberListIterator::MemberListIterator(const MemberList &l) :
-  QListIterator<MemberDef>(l) 
+  QListIterator<MemberDef>(l)
 {
 }
 
@@ -385,9 +399,9 @@ bool MemberList::declVisible() const
         case MemberType_Service:    // fall through
         case MemberType_Sequence:   // fall through
         case MemberType_Dictionary: // fall through
-        case MemberType_Event:  
+        case MemberType_Event:
           return TRUE;
-        case MemberType_Enumeration: 
+        case MemberType_Enumeration:
           {
             // if this is an anonymous enum and there are variables of this
             // enum type (i.e. enumVars>0), then we do not show the enum here.
@@ -399,7 +413,7 @@ bool MemberList::declVisible() const
           break;
         case MemberType_Friend:
           return TRUE;
-        case MemberType_EnumValue: 
+        case MemberType_EnumValue:
           {
             if (m_inGroup)
             {
@@ -431,7 +445,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
   }
   //printf("  --> writePlainDeclaration() numDecMembers()=%d\n",
   //    numDecMembers());
-  
+
   ol.pushGeneratorState();
 
   bool first=TRUE;
@@ -460,13 +474,13 @@ void MemberList::writePlainDeclarations(OutputList &ol,
         case MemberType_Service:     // fall through
         case MemberType_Sequence:    // fall through
         case MemberType_Dictionary:  // fall through
-        case MemberType_Event:  
+        case MemberType_Event:
           {
             if (first) ol.startMemberList(),first=FALSE;
             md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
             break;
           }
-        case MemberType_Enumeration: 
+        case MemberType_Enumeration:
           {
             // if this is an anonymous enum and there are variables of this
             // enum type (i.e. enumVars>0), then we do not show the enum here.
@@ -531,7 +545,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
         case MemberType_Friend:
           if (inheritedFrom==0)
           {
-            if (first) 
+            if (first)
             {
               ol.startMemberList();
               first=FALSE;
@@ -539,7 +553,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
             md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
             break;
           }
-        case MemberType_EnumValue: 
+        case MemberType_EnumValue:
           {
             if (m_inGroup)
             {
@@ -565,7 +579,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
         //printf("anonymous compound members\n");
         if (md->isBriefSectionVisible())
         {
-          if (first) 
+          if (first)
           {
             ol.startMemberList();
             first=FALSE;
@@ -576,10 +590,10 @@ void MemberList::writePlainDeclarations(OutputList &ol,
       }
     }
   }
- 
-  if (!first) 
+
+  if (!first)
   {
-    ol.endMemberList(); 
+    ol.endMemberList();
   }
 
   ol.popGeneratorState();
@@ -635,7 +649,7 @@ void MemberList::writeDeclarations(OutputList &ol,
       if (title)
       {
         ol.writeInheritedSectionTitle(inheritId,cd->getReference(),
-                                      cd->getOutputFileBase(), 
+                                      cd->getOutputFileBase(),
                                       cd->anchor(),title,cd->displayName());
       }
       ol.popGeneratorState();
@@ -643,7 +657,7 @@ void MemberList::writeDeclarations(OutputList &ol,
   }
   else if (num>numEnumValues)
   {
-    if (title) 
+    if (title)
     {
       if (showInline)
       {
@@ -663,7 +677,7 @@ void MemberList::writeDeclarations(OutputList &ol,
         ol.endMemberHeader();
       }
     }
-    if (subtitle) 
+    if (subtitle)
     {
       QCString st=subtitle;
       st = st.stripWhiteSpace();
@@ -728,7 +742,7 @@ void MemberList::writeDeclarations(OutputList &ol,
       }
     }
   }
-  if (inheritedFrom && cd) 
+  if (inheritedFrom && cd)
   {
     // also add members that of this list type, that are grouped together
     // in a separate list in class 'inheritedFrom'
@@ -772,7 +786,7 @@ void MemberList::writeDocumentation(OutputList &ol,
   overloadCountDict.setAutoDelete(TRUE);
   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
   {
-    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && 
+    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) &&
         !(md->isEnumValue() && !showInline))
     {
       uint *pCount = overloadTotalDict.find(md->name());
@@ -790,7 +804,7 @@ void MemberList::writeDocumentation(OutputList &ol,
 
   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
   {
-    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && 
+    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) &&
         !(md->isEnumValue() && !showInline))
     {
       uint overloadCount = *overloadTotalDict.find(md->name());
@@ -949,7 +963,7 @@ void MemberList::addListReferences(Definition *def)
         MemberDef *vmd;
         for ( ; (vmd=vmli.current()) ; ++vmli)
         {
-          //printf("   adding %s\n",vmd->name().data());  
+          //printf("   adding %s\n",vmd->name().data());
           vmd->addListReference(def);
         }
       }
@@ -990,7 +1004,7 @@ void MemberList::setNeedsSorting(bool b)
   m_needsSorting = b;
 }
 
-QCString MemberList::listTypeAsString(MemberListType type) 
+QCString MemberList::listTypeAsString(MemberListType type)
 {
   switch(type)
   {
@@ -1087,16 +1101,7 @@ void MemberList::writeTagFile(FTextStream &tagFile)
 
 int MemberSDict::compareValues(const MemberDef *c1, const MemberDef *c2) const
 {
-  //printf("MemberSDict::compareValues(%s,%s)\n",c1->name().data(),c2->name().data());
-  int cmp = qstricmp(c1->name(),c2->name());
-  if (cmp)
-  {
-    return cmp;
-  }
-  else
-  {
-    return c1->getDefLine()-c2->getDefLine();
-  }
+  return genericCompareMembers(c1,c2);
 }
 
 
commit cd581388f3d013c501e3cefbaf3e81cf93d46fcb
Author: Dimitri van Heesch <doxygen@gmail.com>
Date:   Sun Apr 19 14:21:18 2020 +0200

    issue #7706: Md5 hash does not match for two different runs (part 2)

diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp
index e386af98..20ce4c1b 100644
--- a/src/dotfilepatcher.cpp
+++ b/src/dotfilepatcher.cpp
@@ -132,7 +132,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath,
   //bool isXLink=FALSE;
   int len = 6;
   int indexS = buf.find("href=\""), indexE;
-  bool setTarget = FALSE;
+  bool targetAlreadySet = buf.find("target=")!=-1;
   if (indexS>5 && buf.find("xlink:href=\"")!=-1) // XLink href (for SVG)
   {
     indexS-=6;
@@ -152,9 +152,9 @@ static QCString replaceRef(const QCString &buf,const QCString relPath,
         // fake ref node to resolve the url
         DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context );
         result+=externalRef(relPath,df->ref(),TRUE);
-        if (!df->file().isEmpty())  
+        if (!df->file().isEmpty())
           result += df->file().data() + Doxygen::htmlFileExtension;
-        if (!df->anchor().isEmpty()) 
+        if (!df->anchor().isEmpty())
           result += "#" + df->anchor();
         delete df;
         result += "\"";
@@ -174,7 +174,6 @@ static QCString replaceRef(const QCString &buf,const QCString relPath,
         if (!ref.isEmpty())
         {
           result = externalLinkTarget(true);
-          if (result != "") setTarget = TRUE;
         }
         result+= href+"=\"";
         result+=externalRef(relPath,ref,TRUE);
@@ -185,12 +184,14 @@ static QCString replaceRef(const QCString &buf,const QCString relPath,
         result = href+"=\"" + link + "\"";
       }
     }
-    if (!target.isEmpty() && !setTarget)
+    if (!target.isEmpty() && !targetAlreadySet)
     {
       result+=" target=\""+target+"\"";
     }
     QCString leftPart = buf.left(indexS);
     QCString rightPart = buf.mid(indexE+1);
+    //printf("replaceRef(\n'%s'\n)->\n'%s+%s+%s'\n",
+    //    buf.data(),leftPart.data(),result.data(),rightPart.data());
     return leftPart + result + rightPart;
   }
   else
@@ -215,7 +216,7 @@ bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName,
                     const QCString &context)
 {
   QFile f(mapName);
-  if (!f.open(IO_ReadOnly)) 
+  if (!f.open(IO_ReadOnly))
   {
     err("problems opening map file %s for inclusion in the docs!\n"
       "If you installed Graphviz/dot after a previous failing run, \n"
@@ -250,7 +251,7 @@ bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName,
   return TRUE;
 }
 
-DotFilePatcher::DotFilePatcher(const char *patchFile) 
+DotFilePatcher::DotFilePatcher(const char *patchFile)
   : m_patchFile(patchFile)
 {
   m_maps.setAutoDelete(TRUE);
@@ -346,7 +347,7 @@ bool DotFilePatcher::run() const
   }
   QFile fi(tmpName);
   QFile fo(patchFile);
-  if (!fi.open(IO_ReadOnly)) 
+  if (!fi.open(IO_ReadOnly))
   {
     err("problem opening file %s for patching!\n",tmpName.data());
     QDir::current().rename(tmpName,patchFile);
@@ -380,7 +381,7 @@ bool DotFilePatcher::run() const
     ASSERT(numBytes<maxLineLen);
     if (isSVGFile)
     {
-      if (interactiveSVG_local) 
+      if (interactiveSVG_local)
       {
         if (line.find("<svg")!=-1 && !replacedHeader)
         {
@@ -412,7 +413,7 @@ bool DotFilePatcher::run() const
           replacedHeader=TRUE;
         }
       }
-      if (!insideHeader || !foundSize) // copy SVG and replace refs, 
+      if (!insideHeader || !foundSize) // copy SVG and replace refs,
                                        // unless we are inside the header of the SVG.
                                        // Then we replace it with another header.
       {
@@ -508,7 +509,7 @@ bool DotFilePatcher::run() const
     // dummy link by real ones
     fi.setName(tmpName);
     fo.setName(orgName);
-    if (!fi.open(IO_ReadOnly)) 
+    if (!fi.open(IO_ReadOnly))
     {
       err("problem opening file %s for reading!\n",tmpName.data());
       return FALSE;
@@ -602,18 +603,18 @@ bool DotFilePatcher::writeSVGFigureLink(FTextStream &out,const QCString &relPath
     if (height<=60) height=300; else height+=300; // add some extra space for zooming
     if (height>600) height=600; // clip to maximum height of 600 pixels
     out << "<div class=\"zoom\">";
-    //out << "<object type=\"image/svg+xml\" data=\"" 
-    //out << "<embed type=\"image/svg+xml\" src=\"" 
-    out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" 
+    //out << "<object type=\"image/svg+xml\" data=\""
+    //out << "<embed type=\"image/svg+xml\" src=\""
+    out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\""
         << relPath << baseName << ".svg\" width=\"100%\" height=\"" << height << "\">";
   }
   else
   {
-    //out << "<object type=\"image/svg+xml\" data=\"" 
-    //out << "<embed type=\"image/svg+xml\" src=\"" 
-    out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" 
-        << relPath << baseName << ".svg\" width=\"" 
-        << ((width*96+48)/72) << "\" height=\"" 
+    //out << "<object type=\"image/svg+xml\" data=\""
+    //out << "<embed type=\"image/svg+xml\" src=\""
+    out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\""
+        << relPath << baseName << ".svg\" width=\""
+        << ((width*96+48)/72) << "\" height=\""
         << ((height*96+48)/72) << "\">";
   }
   writeSVGNotSupported(out);
@@ -650,7 +651,7 @@ bool DotFilePatcher::writeVecGfxFigure(FTextStream &out,const QCString &baseName
   }
   //printf("Got PDF/EPS size %d,%d\n",width,height);
   int maxWidth  = 350;  /* approx. page width in points, excl. margins */
-  int maxHeight = 550;  /* approx. page height in points, excl. margins */ 
+  int maxHeight = 550;  /* approx. page height in points, excl. margins */
   out << "\\nopagebreak\n"
          "\\begin{figure}[H]\n"
          "\\begin{center}\n"
diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp
index e622dd4f..c0cc4fdf 100644
--- a/src/dotgraph.cpp
+++ b/src/dotgraph.cpp
@@ -74,15 +74,6 @@ static bool checkDeliverables(const QCString &file1,
   return file1Ok && file2Ok;
 }
 
-static void removeDotGraph(const QCString &dotName)
-{
-  if (Config_getBool(DOT_CLEANUP))
-  {
-    QDir d;
-    d.remove(dotName);
-  }
-}
-
 static bool insertMapFile(FTextStream &out,const QCString &mapFile,
                           const QCString &relPath,const QCString &mapLabel)
 {
@@ -108,7 +99,7 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile,
 QCString DotGraph::imgName() const
 {
   return m_baseName + ((m_graphFormat == GOF_BITMAP) ?
-                      ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); 
+                      ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps"));
 }
 
 QCString DotGraph::writeGraph(
@@ -166,7 +157,6 @@ bool DotGraph::prepareDotFile()
      )
   {
     // all needed files are there
-    removeDotGraph(absDotName());
     return FALSE;
   }