Patch against SVN trunk

Brendon Costa <[email protected]>
Newsgroups gmane.text.doxygen.devel
Message-ID <[email protected]>
Hi doxygen devs,

I have attached a patch for Doxygen that provides some features
described below. I was wondering if a doxygen dev could look over these
changes and commit them to SVN if they find no problems with them?

The patch was created simply with: svn diff > ../edoc.patch

Please let me know if there are any problems with these changes or if
you dont think they should be accepted into doxygen what i could change
to allow that or why.

If you need any more information about this patch please let me know.
There is also a previous post of mine on doxygen-users (Wrong place for
it i just realised) which describes a set of similar patches i made
against doxygen ver 1.5.1. This has some examples as to what this patch
achieves.

http://sourceforge.net/mailarchive/forum.php?thread_name=46CF99DC.70307%40christian.net&forum_name=doxygen-users

The main purpose for it is so that doxygen can correctly parse files
that are generated by EDoc++ and produce documentation that contains
accurate and detailed information about exception propagation through
C++ code in addition to its normal API documentation. However these
patches are for functionality that is not specific to EDoc++.

For more information on EDoc++ see:
http://edoc.sourceforge.net/

Thanks,
Brendon.



* Added DESTDIR install capability to build

* Added function for comparing two types taking default template
parameters into account (Not a perfect match but does a best effort
match using text comparisons and data existing in doxygen).

* Modified matchArgument2() to match function prototypes taking template
types into acount.

* Modified processing of input files to ocurr in the order specified in
the configuration file instead of in alphabetical order. This allows the
user to determine the order in which appended documentation ocurrs when
a single funciton has multiple blocks of documentation by ensuring that
the file which contains the documentation to be first is listed in the
configuration file before a file whose documentation the user wishes to
come afterwards.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/

_______________________________________________
Doxygen-develop mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/doxygen-develop
edoc.patch (text/x-patch, 9.6 KB)
Index: configure
===================================================================
--- configure	(revision 593)
+++ configure	(working copy)
@@ -435,6 +435,7 @@
 configPWD=`pwd`
 
 cat > .makeconfig <<EOF
+DESTDIR   =
 DOXYGEN   = $configPWD
 TMAKEPATH = $configPWD/tmake/lib/$f_platform
 ENV       = env TMAKEPATH=\$(TMAKEPATH)
@@ -444,7 +445,7 @@
 RM        = rm -f
 CP        = cp
 VERSION   = `cat VERSION`
-INSTALL   = $f_prefix
+INSTALL   = \$(DESTDIR)$f_prefix
 INSTTOOL  = $f_insttool
 DOXYDOCS  = ..
 DOCDIR    = $f_docdir
Index: src/util.cpp
===================================================================
--- src/util.cpp	(revision 593)
+++ src/util.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include <qdir.h>
 #include <qdatetime.h>
 #include <qcache.h>
+#include <qvaluelist.h>
 
 #include "util.h"
 #include "message.h"
@@ -3183,6 +3184,156 @@
   return extractCanonicalType(d,fs,type);
 }
 
+static bool BreakUpType(QString type, QString& prefix, QValueList<QString>& params, QString& suffix)
+{
+   //printf("Breaking up type: %s\n", type.data());
+   params.clear();
+
+   size_t depth = 0;
+   size_t start_param = -1;
+   for (size_t i = 0; i < type.length(); i++)
+   {
+      if (type[i] == '<')
+      {
+         //printf("< index: %d, depth: %d\n", i, depth);
+         depth++;
+         if (depth == 1)
+         {
+            // Then we have a prefix.
+            prefix = type.left(i).stripWhiteSpace();
+            //printf("Prefix: %s, index: %d\n", prefix.data(), i);
+            start_param = i + 1;
+         }
+      }
+      else if (type[i] == '>')
+      {
+         //printf("> index: %d, depth: %d\n", i, depth);
+         depth--;
+         if (depth == 0)
+         {
+            if (start_param != (size_t)-1)
+            {
+               params.append(type.mid(start_param, i - start_param).stripWhiteSpace());
+               //printf("Added param: %s, index: %d, start_param: %d\n", params.last().data(), i, start_param);
+            }
+            // Then we have finished parsing template params, lets obtain the suffix and return.
+            suffix = type.mid(i + 1).stripWhiteSpace();
+            //printf("Suffix: %s, index: %d\n", suffix.data(), i);
+            return true;
+         }
+      }
+      else if (type[i] == ',')
+      {
+         // If inside top level template then we have a new parameter.
+         if (depth == 1)
+         {
+            params.append(type.mid(start_param, i - start_param).stripWhiteSpace());
+            //printf("Added param: %s, index: %d, start_param: %d\n", params.last().data(), i, start_param);
+            start_param = i + 1;
+         }
+      }
+   }
+   
+   prefix = type.stripWhiteSpace();
+   //printf("No template info found. Returning prefix: %s\n", prefix.data());
+   return false;
+}
+
+// This function will return true if the two types are considered the same.
+// It differs from comparison of canonical names in that it breaks the 
+// canonical names into various parts for template types and will match types
+// where default template parameters have been specified explicitly with those
+// that have not been.
+static bool sameType(const QString& left, const QString& right)
+{
+   QString left_prefix;
+   QString left_suffix;
+   QValueList<QString> left_params;
+
+   QString right_prefix;
+   QString right_suffix;
+   QValueList<QString> right_params;
+   
+   BreakUpType(left, left_prefix, left_params, left_suffix);
+   BreakUpType(right, right_prefix, right_params, right_suffix);
+
+   // @@@It seems doxygen has trouble determining the namespace of 
+   // items inside template parameters. In order to get some sembelance of 
+   // correct matching i will use the shortest of the two strings as a 
+   // reference, and if the longer ends with the same contents then there is 
+   // a GOOD chance that it is a match. This will fail if for example in two 
+   // different namespaces there is a class defined called Blah. This method 
+   // may be unable to determine the difference between the two types of Blah, 
+   // but only when used in an overloaded function prototype.
+   
+   
+   
+   // Note: We will consider reference and value types as the same too.
+   // This is due to the way EDoc++ emits funciton names. If the compiler has
+   // decided that the function can have the value passed as a const reference
+   // then EDoc++ will not know that the user requested a pass by value, but 
+   // will just see a pass by reference instead. In the end by considering 
+   // reference types the same as value types for this purpose there is little
+   // difference.
+   
+   // So first we remove trailing " &" from the prefix.
+   if (left_prefix.length() >= 1 && left_prefix.mid(left_prefix.length() - 1) == "&")
+   {
+      left_prefix = left_prefix.mid(0, left_prefix.length() - 1).stripWhiteSpace();
+   }
+   if (right_prefix.length() >= 1 && right_prefix.mid(right_prefix.length() - 1) == "&")
+   {
+      right_prefix = right_prefix.mid(0, right_prefix.length() - 1).stripWhiteSpace();
+   }
+   
+   //printf("Obtaining min size of prefixes.\n");
+   size_t min = left_prefix.length();
+   min = (right_prefix.length() < min ? right_prefix.length() : min);
+   
+   // Check for zero length prefixes. If one is 0 and the other is not then 
+   // assume a failed match in case we are comparing a type ending in & with
+   // a compound type.
+   if (!min && left_prefix.length() != right_prefix.length())
+   {
+      return false;
+   }
+   
+   //printf("Finally getting proper values.\n");
+   left_prefix = left_prefix.mid(left_prefix.length() - min).stripWhiteSpace();
+   right_prefix = right_prefix.mid(right_prefix.length() - min).stripWhiteSpace();
+   
+   // If the prefixes differ then the types do not match.
+   if (left_prefix != right_prefix)
+   {
+      return false;
+   }
+
+   
+   QValueList<QString>::Iterator lt = left_params.begin();
+   QValueList<QString>::Iterator rt = right_params.begin();
+   for (; lt != left_params.end() && rt != right_params.end(); lt++, rt++)
+   {
+      // if the template parameter types are not considered the same then there is a failed match.
+      if (!sameType((*lt), QString(*rt)))
+      {
+         return false;
+      }
+   }
+   
+   // If the suffix types differ then the types do not match.
+   if (right_suffix != left_suffix)
+   {
+      if (!sameType(left_suffix, right_suffix))
+      {
+         return false;
+      }
+   }
+
+   // otherwise the two types are considered the same.
+   return true;
+}
+
+
 static bool matchArgument2(
     Definition *srcScope,FileDef *srcFileScope,Argument *srcA,
     Definition *dstScope,FileDef *dstFileScope,Argument *dstA
@@ -3229,7 +3380,10 @@
     dstA->canType = extractCanonicalArgType(dstScope,dstFileScope,dstA);
   }
 
-  if (srcA->canType==dstA->canType)
+  // Changed from comparison of canonical type names to a more 
+  // complex comparison of types to allow template types with specified default
+  // params to match "more correctly"
+  if (sameType(srcA->canType, dstA->canType))
   {
     MATCH
     return TRUE;
Index: src/doxygen.cpp
===================================================================
--- src/doxygen.cpp	(revision 593)
+++ src/doxygen.cpp	(working copy)
@@ -6899,28 +6899,26 @@
 static void generateFileSources()
 {
   if (documentedHtmlFiles==0) return;
-  if (Doxygen::inputNameList->count()>0)
+  // Ensure that sources are parsed in the order they are specified in the
+  // configuration file and not alphabetical order as was done in the past.
+  for (size_t i = 0; i < Doxygen::inputNameList->count(); i++)
   {
-    FileNameListIterator fnli(*Doxygen::inputNameList); 
-    FileName *fn;
-    for (;(fn=fnli.current());++fnli)
+    FileName *fn = Doxygen::inputNameList->at(i);
+    FileNameIterator fni(*fn);
+    FileDef *fd;
+    for (;(fd=fni.current());++fni)
     {
-      FileNameIterator fni(*fn);
-      FileDef *fd;
-      for (;(fd=fni.current());++fni)
+      if (fd->generateSourceFile()) // sources need to be shown in the output
       {
-        if (fd->generateSourceFile()) // sources need to be shown in the output
-        {
-          msg("Generating code for file %s...\n",fd->docName().data());
-          fd->writeSource(*outputList);
-        }
-        else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
-          // we needed to parse the sources even if we do not show them
-        {
-          msg("Parsing code for file %s...\n",fd->docName().data());
-          fd->parseSource();
-        }
+        msg("Generating code for file %s...\n",fd->docName().data());
+        fd->writeSource(*outputList);
       }
+      else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
+        // we needed to parse the sources even if we do not show them
+      {
+        msg("Parsing code for file %s...\n",fd->docName().data());
+        fd->parseSource();
+      }
     }
   }
 }
@@ -8391,9 +8389,11 @@
     }
   }
 
-  QCString *s=inputFiles.first();
-  while (s)
+  // Process files in order specified in the configuration 
+  // file, not just based on the iterator order.
+  for (size_t i = 0; i < inputFiles.count(); i++)
   {
+    QCString* s = inputFiles.at(i);
     QCString fileName=*s;
     QCString extension;
     int ei = fileName.findRev('.');
@@ -8438,8 +8438,6 @@
     FileDef *fd=findFileDef(Doxygen::inputNameDict,fileName,ambig);
     ASSERT(fd!=0);
     root->createNavigationIndex(rootNav,g_storage,fd);
-
-    s=inputFiles.next();
   }
 }
 
@@ -8598,7 +8596,7 @@
               {
                 fn = new FileName(fi.absFilePath(),name);
                 fn->append(fd);
-                if (fnList) fnList->inSort(fn);
+                if (fnList) fnList->append(fn);
                 fnDict->insert(name,fn);
               }
             }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.