$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r64817 - sandbox/geometry/other/programs/doxygen_xml2qbk
From: barend.gehrels_at_[hidden]
Date: 2010-08-15 10:22:50
Author: barendgehrels
Date: 2010-08-15 10:22:44 EDT (Sun, 15 Aug 2010)
New Revision: 64817
URL: http://svn.boost.org/trac/boost/changeset/64817
Log:
Added class output, defines, etc.
Added:
   sandbox/geometry/other/programs/doxygen_xml2qbk/file_to_string.hpp   (contents, props changed)
Text files modified: 
   sandbox/geometry/other/programs/doxygen_xml2qbk/doxygen_xml2qbk.cpp |   694 ++++++++++++++++++++++++++++++--------- 
   1 files changed, 529 insertions(+), 165 deletions(-)
Modified: sandbox/geometry/other/programs/doxygen_xml2qbk/doxygen_xml2qbk.cpp
==============================================================================
--- sandbox/geometry/other/programs/doxygen_xml2qbk/doxygen_xml2qbk.cpp	(original)
+++ sandbox/geometry/other/programs/doxygen_xml2qbk/doxygen_xml2qbk.cpp	2010-08-15 10:22:44 EDT (Sun, 15 Aug 2010)
@@ -21,6 +21,8 @@
 //   functions as area, so there is not (yet) an overlap
 // - currently still in draft
 
+// Aug 14/15: added classes, defines, various enhancements.
+
 
 #define _CRT_SECURE_NO_WARNINGS
 #define _SCL_SECURE_NO_WARNINGS
@@ -38,6 +40,8 @@
 
 #include <rapidxml.hpp>
 
+#include <file_to_string.hpp>
+
 // -------------------------------------------------------------
 // rapid xml convenience code
 // -------------------------------------------------------------
@@ -83,54 +87,116 @@
 
 // -------------------------------------------------------------
 
+inline std::string keep_after(std::string const& input, std::string const& sig)
+{
+    std::size_t pos = input.rfind(sig);
+    if (pos != std::string::npos)
+    {
+        std::string copy = input.substr(pos + sig.length());
+        return copy;
+    }
+    return input;
+}
 
 
-// -------------------------------------------------------------
-std::string file_to_string(std::string const& filename)
-{
-    std::string result;
 
-	std::ifstream cpp_file(filename.c_str());
-	if (cpp_file.is_open())
-	{
-		while (! cpp_file.eof() )
-		{
-			std::string line;
-			std::getline(cpp_file, line);
-            boost::trim(line);
 
-            result += line;
-        }
-    }
-    return result;
-}
+// -------------------------------------------------------------
+// definitions
+// -------------------------------------------------------------
 
-struct par
+// (template)parameter
+struct param
 {
     std::string name;
     std::string description;
-    std::string type, fulltype;
-    std::string concept;
+    std::string type;
+    std::string fulltype; // post-processed
 };
 
-struct function
+// Basic element, base of a class/struct, function, define
+struct element
 {
     std::string name;
     std::string brief_description, detailed_description;
-    std::string argsstring, definition;
-    std::string return_type;
-    std::string model_of;
     std::string location;
-    std::string paragraphs; 
+    int line; // To sort - Doxygen changes order - we change it back
     std::vector<std::string> snippets;
+    std::vector<std::string> admonitions;
     std::vector<std::string> images;
 
-    std::map<std::string, par> parameters;
-    std::vector<std::string> tparams;
+    std::vector<param> template_parameters;
+    std::vector<param> parameters;
+};
+
+enum function_type { function_define, function_constructor, function_member, function_free };
+
+struct function : public element
+{
+    function_type type;
+    std::string definition, argsstring;
+    std::string return_type, return_description;
+    //std::string paragraphs; 
+
+};
+
+struct class_or_struct : public element
+{
+    std::string name, fullname;
+    std::string model_of;
+    std::vector<function> functions;
+};
+
+struct documentation
+{
+    class_or_struct cos;
+    std::vector<function> functions;
+    std::vector<function> defines;
+};
+
+
+// Predicate for std::find_if
+struct par_by_name
+{
+    par_by_name(std::string const& n)
+        : m_name(n)
+    {}
+
+    inline bool operator()(param const& p)
+    {
+        return p.name == m_name;
+    }
+private :
+    std::string m_name;
+};
+
+template <typename Element>
+struct sort_on_line
+{
+    inline bool operator()(Element const& left, Element const& right)
+    {
+        return left.line < right.line;
+    }
 };
 
+
+static inline void add_or_set(std::vector<param>& parameters, param const& p)
+{
+    std::vector<param>::iterator it = std::find_if(parameters.begin(), parameters.end(), par_by_name(p.name));
+    if (it != parameters.end())
+    {
+        if (it->description.empty()) it->description = p.description;
+        if (it->type.empty()) it->type = p.type;
+        if (it->fulltype.empty()) it->fulltype = p.fulltype;
+    }
+    else
+    {
+        parameters.push_back(p);
+    }
+}
+
 // -------------------------------------------------------------
-static void parse_parameter(rapidxml::xml_node<>* node, par& p)
+static void parse_parameter(rapidxml::xml_node<>* node, param& p)
 {
         if (node != NULL)
         {
@@ -147,6 +213,8 @@
         }
         else if (name == "declname") p.name = node->value();
         else if (name == "parametername") p.name = node->value();
+        // Define: <param><defname>Point</defname></param>
+        else if (name == "defname") p.name = node->value(); // for defines
         else if (name == "para") p.description = node->value();
 
         parse_parameter(node->first_node(), p);
@@ -154,7 +222,9 @@
     }
 }
 
-static void parse_parameter_list(rapidxml::xml_node<>* node, function& f)
+// Definition is a function or a class/struct
+template <typename Parameters>
+static void parse_parameter_list(rapidxml::xml_node<>* node, Parameters& parameters)
 {
         if (node != NULL)
         {
@@ -162,59 +232,70 @@
 
                 if (name == "parameteritem") 
         {
-            par p;
+            param p;
             parse_parameter(node->first_node(), p);
             if (! p.name.empty())
             {
-                // Add or set description
-                typedef std::map<std::string, par>::iterator iterator;
-                iterator it = f.parameters.find(p.name);
-                if (it == f.parameters.end())
+                // Copy its description
+                std::vector<param>::iterator it = std::find_if(parameters.begin(),
+                    parameters.end(), par_by_name(p.name));
+                if (it != parameters.end())
                 {
-                    f.parameters[p.name] = p;
+                    it->description = p.description;
                 }
                 else
                 {
-                    f.parameters[p.name].description = p.description;
+                    parameters.push_back(p);
                 }
             }
         }
                 else if (name == "param") 
         {
             // Element of 'templateparamlist.param (.type,.declname,.defname)'
-            par p;
+            param p;
             parse_parameter(node->first_node(), p);
-            std::string tparam = p.type;
-            if (! p.name.empty())
+
+            // Doxygen handles templateparamlist param's differently:
+            //
+            // Case 1:
+            // <param><type>typename Geometry</type></param>
+            // -> no name, assign type to name, replace typename
+            //
+            // Case 2:
+            // <type>typename</type><declname>CoordinateType</declname><defname>CoordinateType</defname>
+            // -> set full type
+            if (p.name.empty())
+            {
+                // Case 1
+                p.name = p.type;
+                boost::replace_all(p.name, "typename", "");
+                boost::trim(p.name);
+            }
+            else
             {
-                tparam += " ";
-                tparam += p.name;
+                // Case 2
+                p.fulltype = p.type + " " + p.name;
             }
-            f.tparams.push_back(tparam);
+
+            add_or_set(parameters, p);
         }
 
-        parse_parameter_list(node->first_node(), f);
-        parse_parameter_list(node->next_sibling(), f);
+        parse_parameter_list(node->first_node(), parameters);
+        parse_parameter_list(node->next_sibling(), parameters);
     }
 }
 
 
-static void parse_member(rapidxml::xml_node<>* node, std::string const& parent, function& f)
+template <typename Element>
+static void parse_element(rapidxml::xml_node<>* node, std::string const& parent, Element& el)
 {
         if (node != NULL)
         {
         std::string name = node->name();
         std::string full = parent + "." + name;
 
-		if (full == ".name") f.name = node->value();
-        else if (full == ".briefdescription.para") f.brief_description = node->value();
-        else if (full == ".detaileddescription.para") f.detailed_description = node->value();
-        else if (full == ".argsstring") f.argsstring = node->value();
-        else if (full == ".definition") 
-        {
-            f.definition = node->value();
-            boost::replace_all(f.definition, "boost::geometry::", "");
-        }
+        if (full == ".briefdescription.para") el.brief_description = node->value();
+        else if (full == ".detaileddescription.para") el.detailed_description = node->value();
         else if (full == ".location")
         {
             std::string loc = get_attribute(node, "file");
@@ -223,29 +304,74 @@
             {
                 loc = loc.substr(pos + 1);
             }
-            f.location = loc;
+            el.location = loc;
+            el.line = atol(get_attribute(node, "line").c_str());
+        }
+        else if (full == ".detaileddescription.para.qbk.snippet")
+        {
+            el.snippets.push_back(boost::trim_copy(std::string(node->value())));
+        }
+        else if (full == ".detaileddescription.para.qbk.admonition")
+        {
+            el.admonitions.push_back(boost::trim_copy(std::string(node->value())));
+        }
+        else if (full == ".templateparamlist") 
+        {
+            parse_parameter_list(node->first_node(), el.template_parameters);
+        }
+        else if (full == ".detaileddescription.para.parameterlist")
+        {
+            std::string kind = get_attribute(node, "kind");
+            if (kind == "param")
+            {
+                parse_parameter_list(node->first_node(), el.parameters);
+            }
+            else if (kind == "templateparam")
+            {
+                parse_parameter_list(node->first_node(), el.template_parameters);
+            }
+        }
+        
+        parse_element(node->first_node(), full, el);
+        parse_element(node->next_sibling(), parent, el);
+    }
+}
+
+static void parse_function(rapidxml::xml_node<>* node, std::string const& parent, function& f)
+{
+	if (node != NULL)
+	{
+        std::string name = node->name();
+        std::string full = parent + "." + name;
+
+		if (full == ".name") f.name = node->value();
+        else if (full == ".argsstring") f.argsstring = node->value();
+        else if (full == ".definition") 
+        {
+            f.definition = node->value();
+            boost::replace_all(f.definition, "boost::geometry::", "");
         }
         else if (full == ".param")
         {
-            par p;
+            param p;
             parse_parameter(node->first_node(), p);
-            f.parameters[p.name] = p;
+            add_or_set(f.parameters, p);
+        }
+        else if (full == ".type")
+        {
+            f.return_type = node->value();
         }
         else if (full == ".detaileddescription.para.simplesect")
         {
             std::string kind = get_attribute(node, "kind");
             if (kind == "return")
             {
-                get_contents(node->first_node(), f.return_type);
+                get_contents(node->first_node(), f.return_description);
             }
-            else if (kind == "par")
+            /*else if (kind == "param")
             {
                 get_contents(node->first_node(), f.paragraphs);
-            }
-        }
-        else if (full == ".detaileddescription.para.qbk.snippet")
-        {
-            f.snippets.push_back(node->value());
+            }*/
         }
         else if (full == ".detaileddescription.para.image")
         {
@@ -255,94 +381,239 @@
                 f.images.push_back(image);
             }
         }
-        else if (full == ".templateparamlist") 
+        
+        parse_function(node->first_node(), full, f);
+        parse_function(node->next_sibling(), parent, f);
+    }
+}
+
+static void parse(rapidxml::xml_node<>* node, documentation& doc, bool member = false)
+{
+	if (node != NULL)
+	{
+        bool recurse = false;
+        bool is_member = member;
+
+        std::string nodename = node->name();
+
+		if (nodename == "doxygen")
+		{
+            recurse = true;
+		}
+        else if (nodename == "sectiondef")
         {
-            parse_parameter_list(node->first_node(), f);
+            std::string kind = get_attribute(node, "kind");
+            if (kind == "func" )
+            {
+                // Get free function definition
+                recurse = true;
+            }
+            if (kind == "define" )
+            {
+                // Get define or Boost.Geometry registration macro
+                recurse = true;
+            }
+            else if (kind == "public-static-func" || kind == "public-func")
+            {
+                recurse = true;
+                is_member = true;
+            }
         }
-        else if (full == ".detaileddescription.para.parameterlist")
+        else if (nodename == "compounddef")
         {
             std::string kind = get_attribute(node, "kind");
-            if (kind == "param")
+            if (kind == "group")
             {
-                parse_parameter_list(node->first_node(), f);
+                recurse = true;
             }
-            else if (kind == "templateparam")
+            if (kind == "struct" || kind == "class")
             {
-                // Get descriptions of template parameters
-                function tf;
-                parse_parameter_list(node->first_node(), tf);
-                // Map them on the found parameters (which are already typed)
-                typedef std::map<std::string, par>::iterator iterator;
-                for (iterator it = tf.parameters.begin();
-                    it != tf.parameters.end(); ++it)
+                recurse = true;
+                parse_element(node->first_node(), "", doc.cos);
+            }
+        }
+		else if (nodename == "memberdef")
+		{
+            std::string kind = get_attribute(node, "kind");
+            if (kind == "function" || kind == "define")
+            {
+                function f;
+                parse_element(node->first_node(), "", f);
+                parse_function(node->first_node(), "", f);
+                if (kind == "define")
+                {
+                    f.type = function_define;
+                    doc.defines.push_back(f);
+                }
+                else if (member)
                 {
-                    // Find it by type (not by name, so sequentially)
-                    for (iterator fit = f.parameters.begin();
-                        fit != f.parameters.end(); ++fit)
-                    {
-                        if (fit->second.type == it->second.name)
-                        {
-                            fit->second.concept = it->second.description;
-                        }
-                    }
+                    f.type = f.name == doc.cos.name ? function_constructor : function_member;
+                    doc.cos.functions.push_back(f);
+                }
+                else
+                {
+                    f.type = function_free;
+                    doc.functions.push_back(f);
                 }
             }
-        }
-        
-        parse_member(node->first_node(), full, f);
-        parse_member(node->next_sibling(), parent, f);
-    }
-}
+		}
+        else if (nodename == "compoundname")
+        {
+            std::string name = node->value();
+            if (name.find("::") != std::string::npos)
+            {
+                doc.cos.fullname = name;
 
+                // For a class, it should have "boost::something::" before
+                // set its name without namespace
+                doc.cos.name = keep_after(name, "::");
+            }
+        }
+        else
+        {
+            //std::cout << nodename << " ignored." << std::endl;
+        }
 
-void quickbook_output(function const& f, std::ostream& out, int index)
-{
-    // Write the parsed function
-    int arity = f.parameters.size();
-    out << "[section:" << f.name << "_" << arity << " " << f.name << " (" << arity << ")" "]" << std::endl;
-    out << std::endl;
 
-    out << f.brief_description << std::endl;
-    out << std::endl;
+        if (recurse)
+        {
+		    // First recurse into childnodes, then handle next siblings
+		    parse(node->first_node(), doc, is_member);
+        }
+        parse(node->next_sibling(), doc, is_member);
+	}
+}
 
-    out << "[heading Synopsis]" << std::endl;
-    out << "``";
-    if (!f.tparams.empty())
+void quickbook_template_parameter_list(std::vector<param> const& parameters, std::ostream& out, bool name = false)
+{
+    if (!parameters.empty())
     {
         out << "template<" ;
         bool first = true;
-        BOOST_FOREACH(std::string const& tparam, f.tparams)
+        BOOST_FOREACH(param const& p, parameters)
         {
-            out << (first ? "" : ", ") << tparam;
+            out << (first ? "" : ", ") << p.fulltype;
             first = false;
         }
         out << ">" << std::endl;
+    }
+}
 
+
+void quickbook_synopsis(function const& f, std::ostream& out)
+{
+    out << "``";
+    quickbook_template_parameter_list(f.template_parameters, out);
+    switch(f.type)
+    {
+        case function_constructor :
+            out << f.name;
+            break;
+        case function_member :
+            out << f.return_type << " " << f.name;
+            break;
+        case function_free :
+            out << f.definition;
+            break;
+        case function_define :
+            {
+                out << f.name;
+                bool first = true;
+                BOOST_FOREACH(param const& p, f.parameters)
+                {
+                    out << (first ? "(" : ", ") << p.name;
+                    first = false;
+                }
+                if (! first)
+                {
+                    out << ")";
+                }
+            }
+            break;
     }
-    out << f.definition << " " << f.argsstring << "``" << std::endl;
+    out << " " << f.argsstring << "``" << std::endl
+        << std::endl;
+}
+
+void quickbook_header(std::string const& location, std::ostream& out)
+{
+    if (! location.empty())
+    {
+        out << "[heading Header]" << std::endl;
+        if (true)
+        {
+            // TODO: get the alternative headerfiles from somewhere
+            out << "Either" << std::endl << std::endl;
+            out << "`#include <boost/geometry/geometry.hpp>`" << std::endl << std::endl;
+            out << "Or" << std::endl << std::endl;
+        }
+        out << "`#include <" << location << ">`" << std::endl;
+        out << std::endl;
+    }
+}
+
+void quickbook_snippets(std::vector<std::string> const& snippets, std::ostream& out)
+{
+    if (! snippets.empty())
+    {
+        out << "[heading Snippets]" << std::endl;
+        BOOST_FOREACH(std::string const& snippet, snippets)
+        {
+            out << "[" << snippet << "]" << std::endl;
+        }
+        out << std::endl;
+    }
+}
+
+
+void quickbook_output(function const& f, std::ostream& out)
+{
+    // Write the parsed function
+    int arity = (int)f.parameters.size();
+    out << "[section:" << f.name << "_" << arity << " " << f.name << " (" << arity << ")" "]" << std::endl;
     out << std::endl;
 
+    out << f.brief_description << std::endl;
+    out << std::endl;
+
+    out << "[heading Synopsis]" << std::endl;
+    quickbook_synopsis(f, out);
+
     out << "[heading Parameters]" << std::endl;
     out << std::endl;
 
-    out << "[table" << std::endl;
-    out << "[[Type] [Concept] [Name] [Description] ]" << std::endl;
+    out << "[table" << std::endl << "[";
+    if (f.type != function_define)
+    {
+        out << "[Type] [Concept] ";
+    }
+    out << "[Name] [Description] ]" << std::endl;
 
-    typedef std::map<std::string, par>::const_iterator iterator;
-    for (iterator it = f.parameters.begin();
-        it != f.parameters.end(); ++it)
+    BOOST_FOREACH(param const& p, f.parameters)
     {
-        par const& p = it->second;
-        out << "[[" << p.fulltype << "] [" << p.concept << "] [" << p.name << "] [" << p.description << "]]" << std::endl;
+        out << "[";
+        std::vector<param>::const_iterator it = std::find_if(f.template_parameters.begin(),
+            f.template_parameters.end(), par_by_name(p.type));
+
+        if (f.type != function_define)
+        {
+            out << "[" << p.fulltype 
+                << "] [" << (it == f.template_parameters.end() ? "" : it->description) 
+                << "] ";
+        }
+        out << "[" << p.name 
+            << "] [" << p.description 
+            << "]]" 
+            << std::endl;
     }
     out << "]" << std::endl;
     out << std::endl;
     out << std::endl;
 
-    if (! f.return_type.empty())
+    if (! f.return_description.empty())
     {
         out << "[heading Returns]" << std::endl;
-        out << f.return_type << std::endl;
+        out << f.return_description << std::endl;
         out << std::endl;
     }
 
@@ -350,78 +621,155 @@
     out << f.detailed_description << std::endl;
     out << std::endl;
 
-    if (! f.model_of.empty())
+    /*if (! f.model_of.empty())
     {
         out << "[heading Model of]" << std::endl;
         out << f.model_of << std::endl;
         out << std::endl;
+    }*/
+
+    BOOST_FOREACH(std::string const& admonition, f.admonitions)
+    {
+        out << admonition << std::endl;
+    }
+
+    quickbook_header(f.location, out);
+    quickbook_snippets(f.snippets, out);
+
+    if (! f.images.empty())
+    {
+        out << "[heading Image(s)]" << std::endl;
+        BOOST_FOREACH(std::string const& image, f.images)
+        {
+            out << "[$" << image << "]" << std::endl;
+        }
     }
+    out << std::endl;
+
+    out << "[endsect]" << std::endl;
+    out << std::endl;
+}
+
 
-    out << "[heading Header]" << std::endl;
-    if (true)
+void quickbook_short_output(function const& f, std::ostream& out)
+{
+    BOOST_FOREACH(param const& p, f.parameters)
     {
-        // TODO: get the alternative headerfiles from somewhere
-        out << "Either" << std::endl << std::endl;
-        out << "`#include <boost/geometry/geometry.hpp>`" << std::endl << std::endl;
-        out << "Or" << std::endl << std::endl;
+        out << "[* " << p.fulltype << "]: ['" << p.name << "]:  " << p.description << std::endl << std::endl;
     }
-    out << "`#include <" << f.location << ">`" << std::endl;
     out << std::endl;
+    out << std::endl;
+
+    if (! f.return_description.empty())
+    {
+        out << "][" << std::endl;
+        out << f.return_description << std::endl;
+        out << std::endl;
+    }
+
 
     if (! f.snippets.empty())
     {
-        out << "[heading Snippets]" << std::endl;
+        out << std::endl << std::endl << "[*Snippets]" << std::endl;
         BOOST_FOREACH(std::string const& snippet, f.snippets)
         {
             out << "[" << snippet << "]" << std::endl;
         }
     }
     out << std::endl;
+}
 
-    if (! f.images.empty())
+void quickbook_output(class_or_struct const& cos, std::ostream& out)
+{
+    std::string short_name = boost::replace_all_copy(cos.fullname, "boost::geometry::", "");
+    
+
+    // Write the parsed function
+    out << "[section:" << short_name << " " << short_name << "]" << std::endl
+        << std::endl;
+
+    out << "[heading Description]" << std::endl
+        << cos.detailed_description << std::endl 
+        << std::endl;
+
+
+    out << "[heading Synopsis]" << std::endl
+        << "``";
+    quickbook_template_parameter_list(cos.template_parameters, out);
+    out << "class " << short_name << std::endl
+        << "{" << std::endl
+        << "  // ..." << std::endl
+        << "};" << std::endl
+        << "``" << std::endl << std::endl;
+
+    if (! cos.template_parameters.empty())
     {
-        out << "[heading Image(s)]" << std::endl;
-        BOOST_FOREACH(std::string const& image, f.images)
+        out << "[heading Template parameter(s)]" << std::endl
+            << "[table" << std::endl
+            << "[[Parameter] [Description]]" << std::endl;
+
+        BOOST_FOREACH(param const& p, cos.template_parameters)
         {
-            out << "[$" << image << "]" << std::endl;
+            out << "[[" << p.fulltype << "] [" << p.description << "]]" << std::endl;
         }
+        out << "]" << std::endl 
+            << std::endl;
     }
-    out << std::endl;
 
-    out << "[endsect]" << std::endl;
-    out << std::endl;
-}
 
-static void parse_function(rapidxml::xml_node<>* node, std::ostream& out, std::vector<function>& functions)
-{
-	if (node != NULL)
-	{
-        bool recurse = false;
-		if (! strcmp(node->name(), "doxygen")
-            || ! strcmp(node->name(), "compounddef")
-            || ! strcmp(node->name(), "sectiondef")
-            )
-		{
-            recurse = true;
-		}
-		else if (! strcmp(node->name(), "memberdef"))
-		{
-            std::string kind = get_attribute(node, "kind");
-            if (kind == "function")
+    std::map<function_type, int> counts;
+    BOOST_FOREACH(function const& f, cos.functions)
+    {
+        counts[f.type]++;
+    }
+
+    if (counts[function_constructor] > 0)
+    {
+        out << "[heading Constructor(s)]" << std::endl
+            << "[table" << std::endl
+            << "[[Function] [Description] [Parameters] ]" << std::endl;
+
+        BOOST_FOREACH(function const& f, cos.functions)
+        {
+            if (f.type == function_constructor)
             {
-                function f;
-                parse_member(node->first_node(), "", f);
-                functions.push_back(f);
+                out << "[[";
+                quickbook_synopsis(f, out);
+                out << "] [" << f.brief_description << "] [";
+                quickbook_short_output(f, out);   
+                out << "]]" << std::endl;
             }
-		}
+        }
+        out << "]" << std::endl 
+            << std::endl;
+    }
 
-        if (recurse)
+    if (counts[function_member] > 0)
+    {
+        out << "[heading Member Function(s)]" << std::endl
+            << "[table" << std::endl
+            << "[[Function] [Description] [Parameters] [Returns] ]" << std::endl;
+
+        BOOST_FOREACH(function const& f, cos.functions)
         {
-		    // First recurse into childnodes, then handle next siblings
-		    parse_function(node->first_node(), out, functions);
+            if (f.type == function_member)
+            {
+                out << "[[";
+                quickbook_synopsis(f, out);
+                out << "] [" << f.brief_description << "] [";
+                quickbook_short_output(f, out);   
+                out << "]]" << std::endl;
+            }
         }
-        parse_function(node->next_sibling(), out, functions);
-	}
+        out << "]" << std::endl 
+            << std::endl;
+    }
+
+    quickbook_header(cos.location, out);
+    quickbook_snippets(cos.snippets, out);
+
+    out << "[endsect]" << std::endl
+        << std::endl;
 }
 
 
@@ -432,19 +780,35 @@
     std::string filename = 
         argc > 1 
             ? argv[1] 
-            : "../../../libs/geometry/doc/qbk/doxygen_output/xml/group__simplify.xml";
+            //: "../../../libs/geometry/doc/doxygen_output/xml/structboost_1_1geometry_1_1strategy_1_1distance_1_1pythagoras.xml";
+            //: "../../../libs/geometry/doc/doxygen_output/xml/classboost_1_1geometry_1_1point.xml";
+            //: "../../../libs/geometry/doc/doxygen_output/xml/group__simplify.xml";
+            : "../../../libs/geometry/doc/doxygen_output/xml/group__register.xml"; 
 
-    std::string xml = file_to_string(filename);
+    std::string xml_string = file_to_string(filename);
 
-    xml_doc doc(xml.c_str());
+    xml_doc xml(xml_string.c_str());
     
-    std::vector<function> functions;
-    parse_function(doc.first_node(), std::cout, functions);
+    documentation doc;
+    parse(xml.first_node(), doc);
+
+    std::cout 
+        << "[/ Generated by doxygen_xml2qbk, don't change, it will be overwritten automatically]" << std::endl
+        << "[/ Generated from " << filename << "]" << std::endl;
+
+    BOOST_FOREACH(function const& f, doc.functions)
+    {
+        quickbook_output(f, std::cout);        
+    }
+    BOOST_FOREACH(function const& f, doc.defines)
+    {
+        quickbook_output(f, std::cout);        
+    }
 
-    int i = 0;
-    BOOST_FOREACH(function const& f, functions)
+    if (! doc.cos.name.empty())
     {
-        quickbook_output(f, std::cout, i++);        
+        std::sort(doc.cos.functions.begin(), doc.cos.functions.end(), sort_on_line<function>());
+        quickbook_output(doc.cos, std::cout);        
     }
 
     return 0;
Added: sandbox/geometry/other/programs/doxygen_xml2qbk/file_to_string.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/other/programs/doxygen_xml2qbk/file_to_string.hpp	2010-08-15 10:22:44 EDT (Sun, 15 Aug 2010)
@@ -0,0 +1,38 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+#ifndef FILE_TO_STRING_HPP
+#define FILE_TO_STRING_HPP
+
+
+#include <string>
+#include <fstream>
+
+#include <boost/algorithm/string.hpp>
+
+inline std::string file_to_string(std::string const& filename)
+{
+    std::string result;
+
+    std::ifstream cpp_file(filename.c_str());
+    if (cpp_file.is_open())
+    {
+        while (! cpp_file.eof() )
+        {
+            std::string line;
+            std::getline(cpp_file, line);
+            boost::trim(line);
+
+            result += line;
+        }
+    }
+    return result;
+}
+
+
+#endif // FILE_TO_STRING_HPP