$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r83557 - in trunk/tools/regression: build src/report xsl_reports
From: steven_at_[hidden]
Date: 2013-03-25 11:47:19
Author: steven_watanabe
Date: 2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
New Revision: 83557
URL: http://svn.boost.org/trac/boost/changeset/83557
Log:
Initial replacement for the xsl report generation.
Added:
   trunk/tools/regression/src/report/
   trunk/tools/regression/src/report/add_expected_results.cpp   (contents, props changed)
   trunk/tools/regression/src/report/add_expected_results.hpp   (contents, props changed)
   trunk/tools/regression/src/report/boost_report.cpp   (contents, props changed)
   trunk/tools/regression/src/report/common.cpp   (contents, props changed)
   trunk/tools/regression/src/report/common.hpp   (contents, props changed)
   trunk/tools/regression/src/report/html.cpp   (contents, props changed)
   trunk/tools/regression/src/report/html.hpp   (contents, props changed)
   trunk/tools/regression/src/report/html_writer.hpp   (contents, props changed)
   trunk/tools/regression/src/report/issues_page.cpp   (contents, props changed)
   trunk/tools/regression/src/report/issues_page.hpp   (contents, props changed)
   trunk/tools/regression/src/report/links_page.cpp   (contents, props changed)
   trunk/tools/regression/src/report/links_page.hpp   (contents, props changed)
   trunk/tools/regression/src/report/produce_expected_results.cpp   (contents, props changed)
   trunk/tools/regression/src/report/produce_expected_results.hpp   (contents, props changed)
   trunk/tools/regression/src/report/result_page.cpp   (contents, props changed)
   trunk/tools/regression/src/report/result_page.hpp   (contents, props changed)
   trunk/tools/regression/src/report/runners.cpp   (contents, props changed)
   trunk/tools/regression/src/report/runners.hpp   (contents, props changed)
   trunk/tools/regression/src/report/summary_page.cpp   (contents, props changed)
   trunk/tools/regression/src/report/summary_page.hpp   (contents, props changed)
   trunk/tools/regression/src/report/xml.cpp   (contents, props changed)
   trunk/tools/regression/src/report/xml.hpp   (contents, props changed)
   trunk/tools/regression/src/report/zip.hpp   (contents, props changed)
Text files modified: 
   trunk/tools/regression/build/Jamroot.jam                |    17 +++++++++++++++++                       
   trunk/tools/regression/xsl_reports/boost_wide_report.py |    29 +++++++++++++++++++++++++++++           
   trunk/tools/regression/xsl_reports/build_results.sh     |    22 +++++++++++++++-------                  
   3 files changed, 61 insertions(+), 7 deletions(-)
Modified: trunk/tools/regression/build/Jamroot.jam
==============================================================================
--- trunk/tools/regression/build/Jamroot.jam	(original)
+++ trunk/tools/regression/build/Jamroot.jam	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -82,3 +82,20 @@
     release
     ;
 explicit library_status ;
+
+exe boost_report
+    :
+    [ glob report/*.cpp ]
+    /boost/filesystem//boost_filesystem/<link>static
+    /boost//filesystem/<link>static
+    /boost//date_time/<link>static
+    /boost//regex/<link>static
+    /boost//program_options/<link>static
+    /boost//iostreams/<link>static
+    :
+    <define>BOOST_ALL_NO_LIB=1
+    <use>/boost//headers
+    :
+    release
+    ;
+explicit boost_report ;
Added: trunk/tools/regression/src/report/add_expected_results.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/add_expected_results.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,213 @@
+// Copyright MetaCommunications, Inc. 2003-2007.
+// Copyright Steven Watanabe 2010
+//
+// Distributed under 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)
+
+#include "add_expected_results.hpp"
+#include "common.hpp"
+#include "xml.hpp"
+#include <string>
+#include <boost/foreach.hpp>
+#include <boost/functional/hash.hpp>
+
+using namespace boost::regression;
+
+bool target_result(const test_structure_t::test_log_t& test_log, const std::string& name) {
+    boost::unordered_map<std::string, test_structure_t::target_t>::const_iterator pos = test_log.targets.find(name);
+    if(pos != test_log.targets.end()) {
+        return pos->second.result;
+    } else {
+        return false;
+    }
+}
+
+bool is_test_log_complete(const test_structure_t::test_log_t& test_log) {
+    // FIXME: The original XSL function is buggy and
+    // Boost.Build relies on its behavior
+    return true;
+    if(test_log.test_type == "compile" || test_log.test_type == "compile_fail" ||
+        !target_result(test_log, "compile")) {
+        return test_log.targets.count("compile") == 1 &&
+               test_log.targets.count("link") == 0 &&
+               test_log.targets.count("run") == 0;
+    } else if(test_log.test_type == "link" || test_log.test_type == "link_fail" ||
+        test_log.test_type == "" || test_log.test_type == "lib" ||
+        !target_result(test_log, "link")) {
+        return test_log.targets.count("compile") == 1 &&
+               test_log.targets.count("link") == 1 &&
+               test_log.targets.count("run") == 0;
+    } else if(test_log.test_type == "run" || test_log.test_type == "run_fail" ||
+        test_log.test_type == "run_pyd" || test_log.test_type == "run_mpi") {
+        return test_log.targets.count("compile") == 1 &&
+               test_log.targets.count("link") == 1 &&
+               test_log.targets.count("run") == 1;
+    } else {
+        throw std::runtime_error("Unknown test type " + test_log.test_type);
+    }
+}
+
+std::string get_toolset_name(const std::string& toolset, const expected_results_t& expected_results) {
+    expected_results_t::toolset_aliases_t::const_iterator pos = expected_results.toolset_aliases.find(toolset);
+    if(pos != expected_results.toolset_aliases.end()) {
+        return pos->second;
+    } else {
+        return toolset;
+    }
+}
+
+void add_note(test_structure_t::test_log_t& test_log, const std::string& text, const std::string& class_name = "auto-note") {
+    test_log.notes.push_back("<span class=\"" + class_name + "\">" + text + "</span>");
+}
+
+void process_test_log(test_structure_t::test_log_t& test_log,
+                      const failures_markup_t& failures_markup,
+                      const expected_results_t& expected_results) {
+
+    bool is_complete = is_test_log_complete(test_log);
+
+    bool has_failures = false;
+    typedef boost::unordered_map<std::string, test_structure_t::target_t>::const_reference target_ref;
+    BOOST_FOREACH(target_ref target, test_log.targets) {
+        if(!target.second.result) {
+            has_failures = true;
+            break;
+        }
+    }
+
+    bool actual_result = !(has_failures || !is_complete);
+
+    std::string toolset_name = get_toolset_name(test_log.toolset, expected_results);
+
+    const bool* expected_results_test_case = 0;
+    {
+        test_case_t test_id;
+        test_id.library = test_log.library;
+        test_id.test_name = test_log.test_name;
+        test_id.toolset_name = toolset_name;
+        expected_results_t::tests_t::const_iterator pos = expected_results.tests.find(test_id);
+        if(pos != expected_results.tests.end()) {
+            expected_results_test_case = &pos->second;
+        }
+    }
+
+    std::string category = "0";
+    node_ptr test_failures_markup = 0;
+    {
+        boost::unordered_map<std::string, node_ptr>::const_iterator pos = failures_markup.libraries.find(test_log.library);
+        if(pos != failures_markup.libraries.end()) {
+            node_ptr library_markup = pos->second;
+            FOR_EACH_ELEMENT(elem, library_markup) {
+                if(check_name(elem, "test")) {
+                    std::string test_name;
+                    if(lookup_attr(elem, "name", test_name) && re_match(test_name, test_log.test_name)) {
+                        lookup_attr(elem, "category", category);
+                        FOR_EACH_ELEMENT(mark_failure, elem) {
+                            FOR_EACH_ELEMENT(toolset, mark_failure) {
+                                std::string toolset_name;
+                                if(lookup_attr(toolset, "name", toolset_name) && re_match(toolset_name, test_log.toolset)) {
+                                    test_failures_markup = mark_failure;
+                                    goto found_explicit_failure_markup;
+                                }
+                            }
+                        }
+                    }
+                } else if(check_name(elem, "mark-expected-failures")) {
+                    bool has_test = false;
+                    bool has_toolset = false;
+                    FOR_EACH_ELEMENT(subelem, elem) {
+                        std::string name;
+                        bool has_name = lookup_attr(subelem, "name", name);
+                        if(has_name && check_name(subelem, "test") && re_match(name, test_log.test_name)) {
+                            has_test = true;
+                        } else if(has_name && check_name(subelem, "toolset") && re_match(name, test_log.toolset)) {
+                            has_toolset = true;
+                        }
+                        if(has_toolset && has_test) {
+                            test_failures_markup = elem;
+                            goto found_explicit_failure_markup;
+                        }
+                    }
+                }
+            }
+        }
+        found_explicit_failure_markup:;
+    }
+    
+    bool is_new = (expected_results_test_case == 0);
+    bool has_explicit_markup = (test_failures_markup != 0);
+    
+    bool expected_result = !(has_explicit_markup || (expected_results_test_case && !*expected_results_test_case));
+
+    bool status = (expected_result == actual_result);
+    
+    bool unexpected_success = (expected_result == false && actual_result == true);
+    std::string expected_reason;
+    lookup_attr(test_failures_markup, "reason", expected_reason);
+
+    if(unexpected_success && has_explicit_markup) {
+        add_note(test_log,
+                 "This test case was explicitly marked up in \n"
+                 "<a href=\"http://svn.boost.org/svn/boost/{$source}/status/explicit-failures-markup.xml\">\n"
+                 "    status/explicit-failures-markup.xml</a> file in the Boost SVN as \"expected to fail\",\n"
+                 "but is passing. Please consult the notes/output below for more details.\n");
+    }
+    if(has_explicit_markup && lookup_element(test_failures_markup, "note") == 0) {
+        if(unexpected_success) {
+            add_note(test_log,
+                     "No explanation was provided for this markup. Please contact the library \n"
+                     "author(s)/maintainer(s) for more details.\n");
+        } else {
+            add_note(test_log,
+                     "This failure was explicitly marked as expected in \n"
+                     "<a href=\"http://svn.boost.org/svn/boost/{$source}/status/explicit-failures-markup.xml\">\n"
+                     "status/explicit-failures-markup.xml</a> file in the Boost SVN. \n"
+                     "Please contact the library author(s)/maintainer(s) for the explanation of this markup.\n");
+        }
+    }
+    if(node_ptr elem = lookup_element(test_failures_markup, "note")) {
+        test_log.notes.push_back(elem);
+    }
+
+    if(expected_results_test_case && !*expected_results_test_case) {
+        if(unexpected_success) {
+            add_note(test_log,
+                     "This test case used to fail in the reference (\"last-known-good\") release.\n");
+        } else {
+            add_note(test_log,
+                     "This failure was present in the reference (\"last-known-good\") release.\n");
+        }
+    }
+    
+    if(!is_complete && !has_failures) {
+        add_note(test_log,
+            "<b>[Reporting Tools Internal Error]</b> This test case's XML is missing one or more log entries\n"
+            "of the regression run's steps associated with the test case's type (\"" + test_log.test_type + "\").\n"
+            "Please <a href=\"mailto:mailto:boost-testing_at_[hidden]\">contact reporting tools \n"
+            "maintainers</a> about this problem.\n", "internal-error-note");
+    }
+
+    test_log.result = actual_result;
+    test_log.expected_result = expected_result;
+    test_log.expected_reason = expected_reason;
+    test_log.status = status;
+    test_log.is_new = is_new;
+    test_log.category = category;
+}
+
+void boost::regression::add_expected_results(
+    test_structure_t::run_t& tests,
+    const failures_markup_t& failures_markup,
+    const expected_results_t& expected_results)
+{
+    BOOST_FOREACH(test_structure_t::toolset_group_t::reference toolset, tests.toolsets) {
+        BOOST_FOREACH(test_structure_t::toolset_t::reference library, toolset.second) {
+            BOOST_FOREACH(test_structure_t::library_t::reference test_case, library.second) {
+                BOOST_FOREACH(test_structure_t::test_case_t::reference test_log, test_case.second) {
+                    process_test_log(test_log, failures_markup, expected_results);
+                }
+            }
+        }
+    }
+}
Added: trunk/tools/regression/src/report/add_expected_results.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/add_expected_results.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,25 @@
+// add_expected_results.hpp
+//
+// Copyright (c) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanyiong file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef ADD_EXPECTED_RESULTS_HPP_INCLUDED
+#define ADD_EXPECTED_RESULTS_HPP_INCLUDED
+
+#include "xml.hpp"
+
+namespace boost {
+namespace regression {
+
+void add_expected_results(
+    test_structure_t::run_t& tests,
+    const failures_markup_t& failures_markup,
+    const expected_results_t& expected_results);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/boost_report.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/boost_report.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,177 @@
+// boost_report.cpp
+//
+// Copyright (c) 2013
+// Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENCE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "issues_page.hpp"
+#include "links_page.hpp"
+#include "result_page.hpp"
+#include "issues_page.hpp"
+#include "summary_page.hpp"
+#include "add_expected_results.hpp"
+#include "produce_expected_results.hpp"
+#include "runners.hpp"
+#include "xml.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/date_time/posix_time/posix_time_io.hpp>
+#include <boost/foreach.hpp>
+#include <boost/exception/exception.hpp>
+#include <boost/exception/diagnostic_information.hpp>
+#include <boost/program_options.hpp>
+#include <iostream>
+#include <fstream>
+
+using namespace boost::regression;
+
+boost::shared_ptr<boost::zip::zip_archive> global_zip;
+
+int main(int argc, char* argv[]) {
+    boost::program_options::options_description desc;
+    boost::program_options::variables_map vm;
+    desc.add_options()
+        ("input-file", boost::program_options::value<std::vector<std::string> >(), "Runner XML files")
+        ("expected,e", boost::program_options::value<std::string>()->required(), "Expected results file")
+        ("markup,m", boost::program_options::value<std::string>()->required(), "Failures markup file")
+        ("tag", boost::program_options::value<std::string>()->required(), "the tag for the results (i.e. 'trunk')")
+        ("run-date", boost::program_options::value<boost::posix_time::ptime>()->default_value(boost::posix_time::second_clock::universal_time()), "the timestamp of the report")
+        ("reports,r", boost::program_options::value<std::vector<std::string> >(), "The reports to generate")
+        ("css", boost::program_options::value<std::string>(), "The CSS file")
+        ("help,h", "produce a help message")
+        ;
+
+    boost::program_options::positional_options_description p;
+    p.add("input-file", -1);
+
+    try {
+    
+        boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
+            .options(desc).positional(p).run(), vm);
+        boost::program_options::notify(vm);
+
+        boost::posix_time::ptime now = vm["run-date"].as<boost::posix_time::ptime>();
+        std::string tag = vm["tag"].as<std::string>();
+        std::set<std::string> reports;
+        if(vm.count("reports")) {
+            BOOST_FOREACH(const std::string& report, vm["reports"].as<std::vector<std::string> >())
+                reports.insert(report);
+        }
+        std::vector<std::string> warnings;
+        
+        test_structure_t structure;
+        failures_markup_t markup;
+        expected_results_t expected;
+        std::vector<test_structure_t::run_t*> runs;
+        
+        std::cout << "Reading expected results" << std::endl;
+        boost::shared_ptr<document_type> expected_results = read_xml_file(vm["expected"].as<std::string>().c_str());
+        load_expected_results(&*expected_results, expected);
+
+        std::cout << "Reading failures markup" << std::endl;
+        boost::shared_ptr<document_type> failures_markup = read_xml_file(vm["markup"].as<std::string>().c_str());
+        load_failures_markup(&*failures_markup, markup);
+
+        std::ofstream zip_file("report.zip", std::ios_base::binary);
+        zip_file.exceptions(std::ios_base::failbit);
+        global_zip.reset(new boost::zip::zip_archive(zip_file));
+
+        if(vm.count("input-file")) {
+            BOOST_FOREACH(const std::string& file, vm["input-file"].as<std::vector<std::string> >()) {
+                boost::shared_ptr<document_type> test_results;
+                try {
+                    std::cout << "Reading " << file << std::endl;
+                    test_results = read_xml_file(file.c_str());
+                    load_test_structure(&*test_results, structure, runs);
+                    test_structure_t::run_t* test_run = runs.back();
+                    std::cout << "Merging expected results" << std::endl;
+                    add_expected_results(*test_run, markup, expected);
+                    std::cout << "Generating links pages" << std::endl;
+                    // must be run before test_results is discarded
+                    if(reports.count("l"))
+                        links_page(now, markup, *test_run);
+                } catch(std::ios_base::failure& e) {
+                    std::cerr << e.what() << std::endl;
+                } catch(boost::property_tree::detail::rapidxml::parse_error& e) {
+                    std::cerr << e.what() << std::endl;
+                }
+            }
+        }
+
+        std::vector<std::string> modes;
+        modes.push_back("developer");
+        modes.push_back("user");
+
+        if (reports.count("i") != 0) {
+            std::cout << "Generating issues page" << std::endl;
+            issues_list("developer", structure, markup,
+                        true, tag, now, warnings, "");
+        }
+
+        BOOST_FOREACH(const std::string& mode, modes) {
+            if(reports.count(mode.substr(0, 1) + "d"))
+                result_page(structure, markup,
+                            false, tag, now, warnings, mode, "comment.html");
+        }
+
+        BOOST_FOREACH(const std::string& mode, modes) {
+            if(reports.count(mode.substr(0, 1) + "s"))
+                summary_page(mode, tag, now, std::vector<std::string>(),
+                             structure, markup, false);
+        }
+
+        BOOST_FOREACH(const std::string& mode, modes) {
+            if(reports.count(mode.substr(0, 1) + "dr"))
+                result_page(structure, markup,
+                            true, tag, now, warnings, mode, "comment.html");
+        }
+
+        BOOST_FOREACH(const std::string& mode, modes) {
+            if(reports.count(mode.substr(0, 1) + "sr"))
+                summary_page(mode, tag, now, std::vector<std::string>(),
+                             structure, markup, true);
+        }
+
+        if (reports.count("e")) {
+            produce_expected_results(structure);
+        }
+
+        if(reports.count("n")) {
+            runners(structure);
+        }
+
+        if(vm.count("css")) {
+            std::cout << "Writing file master.css" << std::endl;
+            html_writer css("master.css");
+            std::string filename = vm["css"].as<std::string>();
+            std::ifstream input(filename.c_str());
+            if (input) {
+                std::string data(std::istreambuf_iterator<char>(input.rdbuf()), std::istreambuf_iterator<char>());
+                css << data;
+            } else {
+                std::cerr << "warning: Could not open file: " << filename << std::endl;
+            }
+        }
+
+        global_zip.reset();
+
+    } catch(boost::program_options::error& e) {
+        if(vm.count("help")) {
+            std::cerr << desc << std::endl;
+        } else {
+            std::cerr << e.what() << std::endl;
+            return EXIT_FAILURE;
+        }
+    } catch(boost::exception& e) {
+        std::cerr << boost::diagnostic_information(e) << std::endl;
+        return EXIT_FAILURE;
+    } catch(std::exception& e) {
+        std::cerr << e.what() << std::endl;
+        return EXIT_FAILURE;
+    }
+}
Added: trunk/tools/regression/src/report/common.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/common.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,659 @@
+// Copyright MetaCommunications, Inc. 2003-2005.
+// Copyright Steven Watanabe 2010
+//
+// Distributed under 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)
+
+#include "common.hpp"
+#include "xml.hpp"
+#include "html.hpp"
+
+#include <boost/regex.hpp>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/date_time/posix_time/posix_time_io.hpp>
+#include <algorithm>
+#include <set>
+
+using namespace boost::regression;
+
+std::string boost::regression::alternate_mode(const std::string& mode) {
+    if(mode == "user") {
+        return "developer";
+    } else {
+        return "user";
+    }
+}
+
+std::string boost::regression::release_postfix(bool is_release) {
+    if(is_release) {
+        return "_release";
+    } else {
+        return "";
+    }
+}
+
+// safe
+void boost::regression::get_libraries(const test_structure_t& test_structure, std::set<std::string>& out) {
+    typedef boost::unordered_map<std::string, test_structure_t::platform_t>::const_reference outer_elem;
+    BOOST_FOREACH(outer_elem platform, test_structure.platforms) {
+        BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+            BOOST_FOREACH(test_structure_t::toolset_group_t::const_reference toolset, run.toolsets) {
+                BOOST_FOREACH(test_structure_t::toolset_t::const_reference library, toolset.second) {
+                    out.insert(library.first);
+                }
+            }
+        }
+    }
+}
+
+#if 0
+
+    <func:function name="meta:test_case_status">
+        <xsl:param name="explicit_markup"/>
+        <xsl:param name="test_log"/>
+
+        <xsl:variable name="status">
+            <xsl:choose> 
+                 <xsl:when test="meta:is_unusable( $explicit_markup, $test_log/@library, $test_log/@toolset )">
+                     <xsl:text>unusable</xsl:text>
+                 </xsl:when>
+                 <xsl:when test="$test_log/@result='fail' and  $test_log/@status='unexpected' and $test_log/@is-new='no'">
+                     <xsl:text>fail-unexpected</xsl:text>
+                 </xsl:when>
+                 <xsl:when test="$test_log/@result='fail' and  $test_log/@status='unexpected' and $test_log/@is-new='yes'">
+                     <xsl:text>fail-unexpected-new</xsl:text>
+                 </xsl:when>
+                 <xsl:when test="$test_log/@result='success' and  $test_log/@status='unexpected'">
+                     <xsl:text>success-unexpected</xsl:text>
+                 </xsl:when>
+                 <xsl:when test="$test_log/@status='expected'">
+                     <xsl:text>expected</xsl:text>
+                 </xsl:when>
+                 <xsl:otherwise>
+                     <xsl:text>other</xsl:text>
+                 </xsl:otherwise>
+             </xsl:choose>
+         </xsl:variable>
+         <func:result select="$status"/>
+     </func:function>
+
+    <func:function name="meta:is_toolset_required">
+        <xsl:param name="toolset"/>
+        <func:result select="count( $explicit_markup/explicit-failures-markup/mark-toolset[ @name = $toolset and @status='required' ] ) > 0"/>
+    </func:function>
+    
+#endif
+
+bool boost::regression::is_library_beta(const failures_markup_t& explicit_markup, const std::string& library) {
+    boost::unordered_map<std::string, node_ptr>::const_iterator pos = explicit_markup.libraries.find(library);
+    if(pos != explicit_markup.libraries.end()) {
+        return check_attr(pos->second, "status", "beta");
+    }
+    return false;
+}
+
+bool boost::regression::is_test_log_a_test_case(const test_structure_t::test_log_t& test_log) {
+    const std::string& type = test_log.test_type;
+    return type == "compile" || type == "compile_fail" || type == "link" || type == "link_fail" ||
+        type == "run" || type == "run_fail" || type == "run_pyd" || type == "run_mpi";
+}
+
+// Does not assume any constraints on contents of the strings
+bool boost::regression::is_unusable(const failures_markup_t& markup, const std::string& library, const std::string& toolset) {
+    boost::unordered_map<std::string, node_ptr>::const_iterator pos = markup.libraries.find(library);
+    if(pos != markup.libraries.end()) {
+        FOR_EACH_ELEMENT(mark_unusable, pos->second) {
+            if(check_name(mark_unusable, "mark-unusable")) {
+                FOR_EACH_ELEMENT(toolset_node, mark_unusable) {
+                    std::string name;
+                    if(lookup_attr(toolset_node, "name", name) && re_match(name, toolset)) {
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
+void boost::regression::get_unusable(const failures_markup_t& markup,
+                                     const std::string& library,
+                                     const test_structure_t& test_structure,
+                                     boost::unordered_map<std::string, std::size_t>& out,
+                                     std::vector<node_ptr>& notes) {
+    boost::unordered_map<std::string, node_ptr>::const_iterator pos = markup.libraries.find(library);
+    if(pos != markup.libraries.end()) {
+        FOR_EACH_ELEMENT(mark_unusable, pos->second) {
+            if(check_name(mark_unusable, "mark-unusable")) {
+                node_ptr note = 0;
+                std::vector<std::string> toolsets;
+                FOR_EACH_ELEMENT(toolset_node, mark_unusable) {
+                    std::string name;
+                    if(check_name(toolset_node, "toolset") && lookup_attr(toolset_node, "name", name)) {
+                        BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+                            BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                                BOOST_FOREACH(test_structure_t::toolset_group_t::const_reference toolset, run.toolsets) {
+                                    if(re_match(name, toolset.first)) {
+                                        toolsets.push_back(toolset.first);
+                                    }
+                                }
+                            }
+                        }
+                    } else if(check_name(toolset_node, "note")) {
+                        note = toolset_node;
+                    }
+                }
+                if(note != 0 && !toolsets.empty()) {
+                    notes.push_back(note);
+                    BOOST_FOREACH(const std::string& toolset, toolsets) {
+                        out[toolset] = notes.size();
+                    }
+                }
+            }
+        }
+    }
+}
+
+// There are no restrictions on the pattern or the
+// string.  The only special character in the pattern
+// is '*', which matches any number of consecutive characters.
+bool boost::regression::re_match(const std::string& pattern, const std::string& text) {
+    std::string regex_str;
+    std::string special(".[{()\\+?|^$");
+    for(std::size_t i = 0; i < pattern.size(); ++i) {
+        if(pattern[i] == '*') {
+            regex_str += '.';
+        } else if(special.find(pattern[i]) != std::string::npos) {
+            regex_str += '\\';
+        }
+        regex_str += pattern[i];
+    }
+    boost::regex regex(regex_str);
+    return(boost::regex_match(text, regex));
+}
+
+// date-time
+
+// The result is clamped to the range [0,30]
+int boost::regression::timestamp_difference(const boost::posix_time::ptime& x, const boost::posix_time::ptime& y) {
+    boost::posix_time::time_duration diff = y - x;
+    int result = diff.hours() / 24;
+    if(result < 0) return 0;
+    else if(result > 30) return 30;
+    else return result;
+}
+
+std::string boost::regression::format_timestamp(const boost::posix_time::ptime& timestamp) {
+    std::ostringstream stream;
+    stream.imbue(std::locale(std::locale::classic(), new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S +0000")));
+    stream << timestamp;
+    return stream.str();
+}
+    
+// path
+
+// FIXME: The result MUST be a valid filesystem path.
+std::string boost::regression::encode_path(const std::string& path) {
+    std::string result;
+    BOOST_FOREACH(char ch, path) {
+        if(ch == '.' || ch == '/') {
+            ch = '-';
+        }
+        // FIXME: allow only characters from the following set:
+        // "[a-z][A-Z][0-9][-+_. ,()$!~?]...
+        result += ch;
+    }
+    return result;
+}
+
+std::string boost::regression::escape_uri(const std::string& path) {
+    std::string result;
+    BOOST_FOREACH(char ch, path) {
+        if (('a' <= ch && ch <= 'z') ||
+            ('A' <= ch && ch <= 'Z') ||
+            ('0' <= ch && ch <= '9') ||
+            ch == '-' || ch == '_' || ch == '~' || ch == '.' ||
+            // We're intentionally allowing '/' to go through.
+            // to escape it as well, use escape_literal_uri
+            ch == '/' ||
+            // FIXME: reserved characters
+            ch == '+')
+            result += ch;
+        else {
+            unsigned digit = ch;
+            ch &= 0xFF;
+            const char * xdigits = "0123456789ABCDEF";
+            result += '%';
+            result += xdigits[digit >> 4];
+            result += xdigits[digit & 0xF];
+        }
+    }
+    return result;
+}
+
+std::string boost::regression::escape_literal_uri(const std::string& path) {
+    std::string result;
+    BOOST_FOREACH(char ch, path) {
+        // FIXME: Assumes UTF-8
+        if (('a' <= ch && ch <= 'z') ||
+            ('A' <= ch && ch <= 'Z') ||
+            ('0' <= ch && ch <= '9') ||
+            ch == '-' || ch == '_' || ch == '~' || ch == '.')
+            result += ch;
+        else {
+            unsigned digit = ch;
+            ch &= 0xFF;
+            const char * xdigits = "0123456789ABCDEF";
+            result += '%';
+            result += xdigits[digit >> 4];
+            result += xdigits[digit & 0xF];
+        }
+    }
+    return result;
+}
+
+// okay
+std::string boost::regression::output_file_path(const std::string& path) {
+    return("output/" + (encode_path(path) + ".html"));
+}
+
+// okay
+std::string boost::regression::log_file_path(
+    const failures_markup_t& explicit_markup,
+    const test_structure_t::test_log_t& test_log,
+    const std::string& runner,
+    const std::string& release_postfix)
+{
+    if(show_output(explicit_markup, test_log)) {
+        return output_file_path(runner + "-" + test_log.target_directory + release_postfix);
+    } else {
+        return "";
+    }
+}
+
+bool boost::regression::show_library(const failures_markup_t& explicit_markup, const std::string& library, bool release) {
+    return !release || !is_library_beta(explicit_markup, library);
+}
+
+bool boost::regression::show_output(const failures_markup_t& explicit_markup, const test_structure_t::test_log_t& test_log) {
+    return ((!test_log.result || test_log.show_run_output) ||
+        (test_log.result && !test_log.status))
+        && !(is_unusable(explicit_markup, test_log.library, test_log.toolset));
+}
+
+bool boost::regression::show_toolset(const failures_markup_t& explicit_markup, const std::string& toolset, bool release) {
+    return !release || explicit_markup.required_toolsets.find(toolset) != explicit_markup.required_toolsets.end();
+}
+
+// safe: no assumptions, enumerated result
+std::string boost::regression::result_cell_class(const failures_markup_t& explicit_markup,
+                                                 const std::string& library,
+                                                 const std::string& toolset,
+                                                 const test_log_group_t& test_logs) {
+    if(is_unusable(explicit_markup, library, toolset)) {
+        return "unusable";
+    }
+    if(test_logs.empty()) {
+        return "missing";
+    }
+    BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+        if(!log->result && log->expected_result && !log->is_new) {
+            return "fail-unexpected";
+        }
+    }
+    BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+        if(!log->result && log->expected_result && log->is_new) {
+            return "fail-unexpected-new";
+        }
+    }
+    BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+        if(!log->result && log->expected_reason != "") {
+            return "fail-expected-unreasearched";
+        }
+    }
+    BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+        if(!log->result) {
+            return "fail-expected";
+        }
+    }
+    BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+        if(log->result && !log->expected_result) {
+            return "success-unexpected";
+        }
+    }
+    BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+        if(log->result && log->expected_result) {
+            return "success-expected";
+        }
+    }
+    return "unknown";
+}
+// safe
+std::string boost::regression::result_cell_class(const failures_markup_t& explicit_markup,
+                                                 const std::string& library,
+                                                 const std::string& toolset,
+                                                 const test_structure_t::library_t& test_logs)
+{
+    test_log_group_t tmp;
+    BOOST_FOREACH(test_structure_t::library_t::const_reference test_case, test_logs) {
+        BOOST_FOREACH(test_structure_t::test_case_t::const_reference log, test_case.second) {
+            tmp.push_back(&log);
+        }
+    }
+    return result_cell_class(explicit_markup, library, toolset, tmp);
+}
+
+void boost::regression::insert_report_header(
+    html_writer& document,
+    const boost::posix_time::ptime& run_date,
+    const std::vector<std::string>& warnings,
+    const std::string& purpose)
+{
+    document << "<div class=\"report-info\">\n";
+    document << "    <div>\n";
+    document << "        <b>Report Time: </b> " << format_timestamp(run_date) << "\n";
+    document << "    </div>\n";
+
+    if(!purpose.empty()) {
+        document << "    <div>\n";
+        document << "        <b>Purpose: </b> " << escape_xml(purpose) << "\n";
+        document << "    </div>\n";
+    }
+
+    BOOST_FOREACH(const std::string& warning, warnings) {
+        document << "    <div class=\"report-warning\">\n";
+        document << "        <b>Warning: </b>\n";
+        document << "        <a href=\"mailto:boost-testing_at_[hidden]?subject=[Report Pages]%20" << escape_literal_uri(warning) << " (" << format_timestamp(run_date) << ")\" class=\"warning-link\">\n";
+        document << "            " << escape_xml(warning) << "\n";
+        document << "        </a>\n";
+        document << "    </div>\n";
+    }
+
+    document << "</div>\n";
+}
+
+// requires class_ is enumerated
+void boost::regression::insert_view_link(html_writer& out, const std::string& page, const std::string& class_, bool release) {
+    if(release) {
+        out << "<a href=\"" << escape_uri(page) << ".html\" class=\"" << class_ << "\" target=\"_top\">"
+               "Full View"
+               "</a>\n";
+    } else {
+        out << "<a href=\"" << escape_uri(page) << "_release.html\" class=\"" << class_ << "\" target=\"_top\">"
+               "Release View"
+               "</a>";
+    }
+
+}
+
+// requires: mode = developer | user (Should be the opposite of the current page)
+// requires: page is the base name of the current page.  It should be valid
+//           according to encode_path, but should not be URI escaped.
+void boost::regression::insert_page_links(html_writer& document,
+                                          const std::string& page,
+                                          bool release,
+                                          const std::string& mode) {
+    document << "<div class=\"links\">\n"
+             << make_tinyurl
+             << " | ";
+
+    // yes, really.  The class is set to ""
+    insert_view_link(document, page, "", release);
+
+    std::string release_postfix(release? "_release" : "");
+
+    document << " | "
+                "<a href=\"../" << mode << "/" << escape_uri(page) << release_postfix << ".html\" class=\"view-link\" target=\"_top\">"
+             << mode << " View"
+                "</a>"
+                " | "
+                "<a href=\"" << escape_uri(page) << release_postfix << "_.html#legend\">Legend</a>\n"
+
+                "</div>\n";
+
+}
+
+// requires: mode = summary | details
+// requires: top_or_bottom = top | bottom
+void boost::regression::insert_runners_rows(html_writer& document,
+                                            const std::string& mode,
+                                            const std::string& top_or_bottom,
+                                            const test_structure_t& test_structure,
+                                            const boost::posix_time::ptime& run_date) {
+    std::string colspan = (mode == "summary") ? "1" : "2";
+
+    if(top_or_bottom == "top") {
+        document << "<tr>\n"
+                    "    <td colspan=\"" << colspan << "\"> </td>\n";
+        BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+            std::size_t count = 0;
+            BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                count += run.toolsets.size();
+            }
+            if(count > 0) {
+                document << "    <td colspan=\"" << count << "\" class=\"runner\">\n"
+                            "        " << escape_xml(platform.first) << "\n"
+                            "    </td>\n";
+            }
+        }
+        document << "    <td colspan=\"" << colspan << "\"> </td>\n"
+                    "</tr>\n";
+    }
+
+    document << "<tr>\n"
+                "    <td colspan=\"" << colspan << "\"> </td>\n";
+    BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+        BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+            if(run.toolsets.size() > 0) {
+                document << "    <td colspan=\"" << run.toolsets.size() << "\" class=\"runner\">\n"
+                            "        <a href=\"../" << escape_uri(encode_path(run.runner)) << ".html\">\n"
+                            "            " << escape_xml(run.runner) << "\n"
+                            "        </a>\n"
+                            "    </td>\n";
+            }
+        }
+    }
+    document << "    <td colspan=\"" << colspan << "\"> </td>\n"
+                "</tr>\n";
+
+    document << "<tr>\n"
+                "<td colspan=\"" << colspan << "\"> </td>\n";
+    BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+        BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+            if(run.toolsets.size() > 0) {
+                document << "    <td colspan=\"" << run.toolsets.size() << "\" class=\"revision\">\n"
+                            "         rev " << run.revision << "\n"
+                            "    </td>\n";
+            }
+        }
+    }
+    document << "    <td colspan=\"" << colspan << "\"> </td>\n"
+                "</tr>\n";
+    
+    document << "<tr>\n"
+                "    <td colspan=\"" << colspan << "\"> </td>\n";
+    BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+        BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+            if(run.toolsets.size() > 0) {
+                int age = timestamp_difference(run.timestamp, run_date);
+                document << "    <td colspan=\"" << run.toolsets.size() << "\" class=\"timestamp\">\n"
+                            "        <span class=\"timestamp-" << age << "\">" << format_timestamp(run.timestamp) << "</span>";
+                if(run.run_type != "full") {
+                    document << "<span class=\"run-type-" << run.run_type << "\">" << run.run_type[0] << "</span>\n";
+                }
+                document << "    </td>\n";
+            }
+        }
+    }
+    document << "    <td colspan=\"" << colspan << "\"> </td>\n"
+                "</tr>\n";
+
+    if(top_or_bottom == "bottom") {
+        document << "<tr>\n"
+                    "    <td colspan=\"" << colspan << "\"> </td>\n";
+        BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+            std::size_t count = 0;
+            BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                count += run.toolsets.size();
+            }
+            if(count > 0) {
+                document << "    <td colspan=\"" << count << "\" class=\"runner\">\n"
+                            "        " << escape_xml(platform.first) << "\n"
+                            "    </td>\n";
+            }
+        }
+        document << "    <td colspan=\"" << colspan << "\"> </td>\n"
+                    "</tr>\n";
+    }
+}
+
+// requires mode = summary | details
+void boost::regression::insert_toolsets_row(html_writer& document,
+                                            const test_structure_t& test_structure,
+                                            const failures_markup_t& explicit_markup,
+                                            const std::string& mode,
+                                            const boost::posix_time::ptime& run_date,
+                                            const std::string& library,
+                                            const boost::unordered_map<std::string, std::size_t>& library_marks) {
+
+    document << "<tr valign=\"middle\">\n";
+
+    std::string colspan = (mode == "summary") ? "1" : "2";
+    std::string title = (mode == "summary") ?
+        " library / toolset " :
+        " test / toolset ";
+              
+    document << "    <td class=\"head\" colspan=\"" << colspan << "\" width=\"1%\">" << title << "</td>\n";
+    BOOST_FOREACH(const test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+        BOOST_FOREACH(const test_structure_t::platform_t::const_reference run, platform.second) {
+            BOOST_FOREACH(const test_structure_t::toolset_group_t::const_reference toolset, run.toolsets) {
+                std::string name = toolset.first;
+                std::string class_ = (explicit_markup.required_toolsets.find(name) != explicit_markup.required_toolsets.end())?
+                    "required-toolset-name" :
+                    "toolset-name";
+
+                document << "<td class=\"" << class_ << "\">\n";
+                int age = timestamp_difference(run.timestamp, run_date);
+
+                document <<    "<span class=\"timestamp-" << age << "\">\n";
+
+                // break toolset names into words
+                BOOST_FOREACH(char ch, name) {
+                    document << ch;
+                    if(ch == '-') {
+                        document << ' ';
+                    }
+                }
+
+                if(mode == "details") {
+                    //     <!-- prepare toolset notes -->
+                    std::set<std::size_t> toolset_notes;
+                    typedef boost::unordered_map<std::string, std::size_t>::const_reference ref_type;
+                    BOOST_FOREACH(ref_type toolset_markup, library_marks.equal_range(name)) {
+                        toolset_notes.insert(toolset_markup.second);
+                    }
+                    if(!toolset_notes.empty()) {
+                        document << "<span class=\"super\">\n";
+                        bool first = true;
+                        BOOST_FOREACH(std::size_t note_index, toolset_notes) {
+                            if(!first) document << ", "; else first = false;
+                            document << "<a href=\"#" << escape_uri(library) << "-note-" << note_index << "\" title=\"Note " << note_index << "\">\n"
+                                        "    " << note_index << "\n"
+                                        "</a>\n";
+                        }
+                        document << "</span>\n";
+                    }
+                }
+
+                document << "</span>\n"
+                            "</td>\n";
+            }
+        }
+    }
+    document << "<td class=\"head\" width=\"1%\">" << title << "</td>\n"
+                "</tr>\n";
+}
+
+namespace {
+
+std::string get_note_attr(const test_structure_t::note_t& note, const std::string& name) {
+    if(const node_ptr* node = boost::get<node_ptr>(¬e)) {
+        std::string result;
+        lookup_attr(*node, name, result);
+        return result;
+    } else {
+        return std::string();
+    }
+}
+
+}
+
+// requires: if note is a string, it is well-formed html
+void boost::regression::show_note(
+    html_writer& document,
+    const test_structure_t::note_t& note,
+    const std::string& references,
+    const failures_markup_t& explicit_markup)
+{
+    document << "<div class=\"note\">\n";
+
+    std::string author = get_note_attr(note, "author");
+    std::string date = get_note_attr(note, "date");
+
+    document << "    <span class=\"note-header\">\n";
+
+    if(author != "" && date != "") {
+        document << "        [ " << escape_xml(author) << " " << escape_xml(date) << " ]\n";
+    } else if(author != "") {
+        document << "        [ " << escape_xml(author) << " ]\n";
+    } else if(date != "") {
+        document << "        [ " << escape_xml(date) << " ]\n";
+    }
+
+    document << "    </span>\n";
+
+    if(references != "") {
+        // lookup references (refid="17,18")
+        std::vector<std::string> refs;
+        boost::algorithm::split(refs, references, boost::is_any_of(","));
+        BOOST_FOREACH(const std::string& refid, refs) {
+            boost::unordered_map<std::string, node_ptr>::const_iterator pos = explicit_markup.notes.find(refid);
+            if(pos != explicit_markup.notes.end()) {
+                write_contents(document, pos->second);
+            } else {
+                document << "    " << escape_xml(refid) << "\n";
+            }
+        }
+    }
+    if(const node_ptr* node_note = boost::get<node_ptr>(¬e)) {
+        write_contents(document, *node_note);  
+    } else if(const std::string* string_note = boost::get<std::string>(¬e)) {
+        document << *string_note; // not escaped--can contain html markup
+    }
+
+    document << "</div>\n";
+}
+
+// requires: any note that is a string contains well-formed html
+void boost::regression::show_notes(html_writer& document,
+                                   const std::vector<test_structure_t::note_t>& notes,
+                                   const failures_markup_t& explicit_markup)
+{
+    document << "<div class=\"notes\">\n";
+
+    BOOST_FOREACH(const test_structure_t::note_t& note, notes) {
+
+        document << "    <div>\n";
+
+        std::string refid = get_note_attr(note, "refid");
+        ::show_note(document, note, refid, explicit_markup);
+
+        document << "    </div>\n";
+
+    }
+
+    document << "</div>\n";
+}
Added: trunk/tools/regression/src/report/common.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/common.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,109 @@
+// common.hpp
+//
+// Copyright (c) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanyiong file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef COMMON_HPP_INCLUDED
+#define COMMON_HPP_INCLUDED
+
+#include <vector>
+#include <string>
+#include <set>
+#include <boost/filesystem/path.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include "xml.hpp"
+
+namespace boost {
+namespace regression {
+
+class html_writer;
+typedef std::vector<const test_structure_t::test_log_t*> test_log_group_t;
+
+bool is_library_beta(const failures_markup_t& explicit_markup, const std::string& library);
+bool is_test_log_a_test_case(const test_structure_t::test_log_t& test_log);
+
+bool is_unusable(const failures_markup_t& markup, const std::string& library, const std::string& toolset);
+
+void get_unusable(const failures_markup_t& markup,
+                  const std::string& library,
+                  const test_structure_t& test_structure,
+                  boost::unordered_map<std::string, std::size_t>& out,
+                  std::vector<node_ptr>& notes);
+
+bool re_match(const std::string& pattern, const std::string& text);
+
+int timestamp_difference(const boost::posix_time::ptime& x, const boost::posix_time::ptime& y);
+std::string format_timestamp(const boost::posix_time::ptime& timestamp);
+
+std::string encode_path(const std::string& path);
+std::string escape_uri(const std::string& path); // escapes a URI path (leaves '/' alone)
+std::string escape_literal_uri(const std::string& path); // escapes all special characters in a URI
+std::string output_file_path(const std::string& path);
+std::string log_file_path(
+    const failures_markup_t& explicit_markup,
+    const test_structure_t::test_log_t& test_log,
+    const std::string& runner,
+    const std::string& release_postfix = "");
+
+bool show_library(const failures_markup_t& explicit_markup, const std::string& library, bool release);
+bool show_output(const failures_markup_t& markup, const test_structure_t::test_log_t& test_log);
+bool show_toolset(const failures_markup_t& explicit_markup, const std::string& toolset, bool release);
+
+void insert_report_header(html_writer& document,
+                          const boost::posix_time::ptime& run_date,
+                          const std::vector<std::string>& warnings,
+                          const std::string& purpose = "");
+
+void insert_view_link(html_writer& document,
+                      const std::string& page,
+                      const std::string& class_,
+                      bool release);
+
+void insert_page_links(html_writer& document,
+                       const std::string& page,
+                       bool release,
+                       const std::string& mode);
+
+void insert_runners_rows(html_writer& document,
+                         const std::string& mode,
+                         const std::string& top_or_bottom,
+                         const test_structure_t& test_structure,
+                         const boost::posix_time::ptime& run_date);
+
+void insert_toolsets_row(html_writer& document,
+                         const test_structure_t& test_structure,
+                         const failures_markup_t& explicit_markup,
+                         const std::string& mode,
+                         const boost::posix_time::ptime& run_date,
+                         const std::string& library = std::string(),
+                         const boost::unordered_map<std::string, std::size_t>& library_marks = boost::unordered_map<std::string, std::size_t>());
+
+void show_note(
+    html_writer& document,
+    const test_structure_t::note_t& note,
+    const std::string& references,
+    const failures_markup_t& explicit_markup);
+void show_notes(html_writer& document, const std::vector<test_structure_t::note_t>& notes, const failures_markup_t& explicit_markup);
+
+std::string result_cell_class(const failures_markup_t& explicit_markup,
+                              const std::string& library,
+                              const std::string& toolset,
+                              const test_log_group_t& test_logs);
+
+std::string result_cell_class(const failures_markup_t& explicit_markup,
+                              const std::string& library,
+                              const std::string& toolset,
+                              const test_structure_t::library_t& test_logs);
+
+std::string alternate_mode(const std::string& mode);
+std::string release_postfix(bool is_release);
+
+void get_libraries(const test_structure_t& test_structure, std::set<std::string>& out);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/html.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/html.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,345 @@
+// html.cpp
+//
+// Copyright (c) 2010
+// Steven Watanabe
+//
+// Distributed Under 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)
+
+#include "html.hpp"
+
+const char* const boost::regression::make_tinyurl =
+    "<span>"
+    "<script type=\"text/javascript\">\n"
+    "<!--\n"
+    "function make_tinyurl()\n"
+    "{\n"
+    "    window.open( 'http://tinyurl.com/create.php?url=' + parent.location.href );\n"
+    "}\n"
+    "//-->\n"
+    "</script>\n"
+    "\n"
+    "<a href=\"javascript:make_tinyurl()\">TinyUrl</a>"
+    "</span>\n"
+;
+
+const char* const boost::regression::issues_legend =
+    "<div class=\"legend\">\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "<tr>\n"
+    "    <td>\n"
+    "    <table border=\"0\" summary=\"legend\">\n"
+    "        <tr>\n"
+    "            <td>\n"
+    "                <table width=\"100%\" summary=\"unexpected new fail legend\">\n"
+    "                <tr class=\"library-row-single\"><td class=\"library-fail-unexpected-new\"><toolset></td></tr>\n"
+    "                </table>\n"
+    "            </td>\n"
+    "            <td class=\"legend-item\">Failure on a newly added test/compiler.</td>\n"
+    "        </tr>\n"
+    "        <tr>\n"
+    "            <td>\n"
+    "                <table width=\"100%\" summary=\"unexpected fail legend\">\n"
+    "                <tr class=\"library-row-single\"><td class=\"library-fail-unexpected\"><toolset></td></tr>\n"
+    "                </table>\n"
+    "            </td>\n"
+    "            <td class=\"legend-item\">Unexpected failure.</td>\n"
+    "        </tr>\n"
+    "    </table>\n"
+    "    </td>\n"
+    "</tr>\n"
+    "</table>\n"
+    "</div>\n"
+;
+
+const char* const boost::regression::library_user_legend =
+    "<div class=\"legend\">\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"success legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-success-expected user-library-success-expected\">pass</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">The test successfully passes.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"expected fail legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-expected user-library-fail-expected\"><u>fail*</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            A <b>known failure</b> that the library maintainers are aware about. Please follow the link to \n"
+    "            find out how it affects the library's functionality.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unusable legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-unusable user-library-unusable\">unusable</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            The library author marked it as <b>unusable</b> on this particular platform/toolset. Please\n"
+    "            see the corresponding footnote.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unresearched legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-expected-unresearched user-library-fail-expected-unresearched\"><u>fail?</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "          An <b>unsearched failure</b>: the library maintainers are aware of it, but need help with \n"
+    "          investigating/addressing it for future releases. Please follow the link to \n"
+    "          access the details and find out how it affects library functionality. </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected new fail legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-unexpected-new user-library-fail-unexpected-new\"><u>fail</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            A <b>new failure</b> on the test/compiler added in this release that hasn't been accounted for yet. \n"
+    "            Please follow the link to access the details.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected fail legend\">\n"
+    "            <tr class=\"library-row-single user-library-row-single\"><td class=\"library-fail-unexpected\"><u>fail</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "             A <b>regression</b> comparing to the previous release. Please follow the link to \n"
+    "             access the details.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\"></td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "<hr/>\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "    <tr>\n"
+    "        <td><span class=\"run-type-incremental\">i</span></td>\n"
+    "        <td class=\"legend-explanation\">An incremental run.</td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "</div>\n"
+;
+
+const char* const boost::regression::library_developer_legend =
+    "<div class=\"legend\">\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"success legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-success-expected\">pass</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">Success.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected pass legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-success-unexpected\">pass</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">Unexpected success; follow the link for more details.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"expected fail legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-expected\">fail*</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">Expected failure; follow the link for more details.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unusable legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-unusable\">n/a</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">The library author marked it as unusable on this particular platform/toolset.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unresearched legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-expected-unresearched\">fail?</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">Unsearched failure; follow the link for more details.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected new fail legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-unexpected-new\">fail</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">Failure on a newly added test/compiler.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected fail legend\">\n"
+    "            <tr class=\"library-row-single\"><td class=\"library-fail-unexpected\">fail</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">Unexpected failure/regression.</td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\"></td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "<hr/>\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "    <tr>\n"
+    "        <td><span class=\"run-type-incremental\">i</span></td>\n"
+    "        <td class=\"legend-explanation\">An incremental run.</td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "</div>\n"
+;
+
+const char * const boost::regression::summary_user_legend =
+    "<div class=\"legend\">\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"success legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-success-expected user-summary-success-expected\"> pass </td></tr>\n"
+    "                </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            All library's tests pass.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"expected fail legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-fail-expected user-summary-fail-expected\"><u>details</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            Most of the library's tests pass, but there are some <b>known failures</b> which might affect the library's\n"
+    "            functionality. Please follow the link to see the detailed report.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected new fail legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-fail-unexpected-new user-summary-fail-unexpected-new\"><u>details</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            Some of the <b>newly added</b> library's tests fail, or some of the library's tests fail on\n"
+    "            the <b>newly added compiler</b>, or some of the tests fail due to <b>unresearched \n"
+    "            reasons</b>. Please follow the link to see the detailed report.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected fail legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-fail-unexpected user-summary-fail-unexpected\"><u>regress.</u></td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            There are some <b>regressions</b> in the library comparing to the previous release. \n"
+    "            Please follow the link to see the detailed report.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unusable legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-unusable user-summary-unusable\">unusable</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            The library author marked it as <b>unusable</b> on the particular platform/toolset.\n"
+    "            Please follow the link to see the detailed report.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "<hr/>\n"
+    "<table border=\"0\" summary=\"report description\" id=\"Table1\">\n"
+    "    <tr>\n"
+    "        <td><span class=\"run-type-incremental\">i</span></td>\n"
+    "        <td class=\"legend-explanation\">An incremental run.</td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "</div>\n"
+;
+
+const char * const boost::regression::summary_developer_legend =
+    "<div class=\"legend\">\n"
+    "<table border=\"0\" summary=\"report description\">\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"success legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-success-expected\">OK</td></tr>\n"
+    "                </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            All expected tests pass.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected pass legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-success-unexpected\">OK</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            All expected tests pass, and some other tests that were expected to fail \n"
+    "            unexpectedly pass as well.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected new fail legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-fail-unexpected-new\">fail</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            There are some failures on the newly added tests/compiler(s).\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unexpected fail legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-fail-unexpected\">broken</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            Tests that the library author expects to pass are currently failing.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "    <tr>\n"
+    "        <td class=\"legend-item\" width=\"50pt\">\n"
+    "            <table width=\"100%\" summary=\"unusable legend\">\n"
+    "                <tr class=\"summary-row-single\"><td class=\"summary-unusable\">n/a</td></tr>\n"
+    "            </table>\n"
+    "        </td>\n"
+    "        <td class=\"legend-explanation\">\n"
+    "            The library author marked it as unusable on particular platform/toolset.\n"
+    "        </td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "<hr/>\n"
+    "<table border=\"0\" summary=\"report description\" id=\"Table1\">\n"
+    "    <tr>\n"
+    "        <td><span class=\"run-type-incremental\">i</span></td>\n"
+    "        <td class=\"legend-explanation\">An incremental run.</td>\n"
+    "    </tr>\n"
+    "</table>\n"
+    "</div>\n"
+;
Added: trunk/tools/regression/src/report/html.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/html.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,26 @@
+// html.hpp
+//
+// Copyright (c) 2010
+// Steven Watanabe
+//
+// Distributed under 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 HTML_HPP_INCLUDED
+#define HTML_HPP_INCLUDED
+
+namespace boost {
+namespace regression {
+
+extern const char* const make_tinyurl;
+extern const char* const issues_legend;
+extern const char* const library_user_legend;
+extern const char* const library_developer_legend;
+extern const char* const summary_user_legend;
+extern const char* const summary_developer_legend;
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/html_writer.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/html_writer.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,70 @@
+// html_writer.hpp
+//
+// Copyright (c) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanyiong file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef HTML_WRITER_HPP_INCLUDED
+#define HTML_WRITER_HPP_INCLUDED
+
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include "zip.hpp"
+
+#include <cstring>
+
+extern boost::shared_ptr<boost::zip::zip_archive> global_zip;
+
+namespace boost {
+namespace regression {
+
+class html_writer : boost::noncopyable {
+public:
+    // path must be UTF-8 encoded.  The separator is '/'
+    explicit html_writer(const std::string& path)
+      : sink(*global_zip, path)
+    {}
+    ~html_writer() {
+    }
+    html_writer& operator<<(const std::string& arg) {
+        sink.write(arg.data(), arg.size());
+        return *this;
+    }
+    html_writer& operator<<(const char* arg) {
+        sink.write(arg, ::std::strlen(arg));
+        return *this;
+    }
+    html_writer& operator<<(char arg) {
+        sink.write(&arg, 1);
+        return *this;
+    }
+    html_writer& operator<<(std::size_t arg) {
+        char buf[30];
+        char* pos = &buf[0] + 30;
+        if(arg == 0) {
+            *--pos = '0';
+        }
+        for(; arg > 0; arg /= 10) {
+            *--pos = static_cast<char>('0' + (arg % 10));
+        }
+        sink.write(pos, buf + 30 - pos);
+        return *this;
+    }
+    html_writer& operator<<(int arg) {
+        if(arg < 0) *this << '-' << std::size_t(-arg);
+        else *this << std::size_t(arg);
+        return *this;
+    }
+private:
+    boost::zip::deflate_sink sink;
+};
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/issues_page.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/issues_page.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,291 @@
+// issues_page.cpp
+//
+// Copyright MetaCommunications, Inc. 2003-2004.
+// Copyright Steven Watanabe 2010
+//
+// Distributed under 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)
+
+#include "issues_page.hpp"
+#include "html_writer.hpp"
+#include "xml.hpp"
+#include "html.hpp"
+#include "common.hpp"
+
+#include <map>
+#include <string>
+#include <boost/foreach.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/date_time/posix_time/posix_time_io.hpp>
+
+using namespace boost::regression;
+
+typedef std::pair<const test_structure_t::test_log_t*, const std::string*> test_failure_t;
+typedef std::map<std::string, std::map<std::string, std::vector<test_failure_t> > > library_test_names_t;
+typedef std::map<std::string, library_test_names_t> libraries_t;
+
+namespace {
+
+void failing_tests(const test_structure_t& tests,
+                   const failures_markup_t& explicit_markup,
+                   bool release,
+                   libraries_t& out)
+{
+    typedef boost::unordered_map<std::string, test_structure_t::platform_t> test_structure_top;
+    BOOST_FOREACH(test_structure_top::const_reference platform, tests.platforms) {
+        BOOST_FOREACH(const test_structure_t::run_t& runs, platform.second) {
+            BOOST_FOREACH(test_structure_t::toolset_group_t::const_reference toolset, runs.toolsets) {
+                BOOST_FOREACH(test_structure_t::toolset_t::const_reference library, toolset.second) {
+                    BOOST_FOREACH(test_structure_t::library_t::const_reference test_case, library.second) {
+                        BOOST_FOREACH(test_structure_t::test_case_t::const_reference test_log, test_case.second) {
+                            if(test_log.status == false && test_log.result == false &&
+                               explicit_markup.required_toolsets.find(test_log.toolset) != explicit_markup.required_toolsets.end() &&
+                               is_test_log_a_test_case(test_log) &&
+                               show_library(explicit_markup, library.first, release) &&
+                               show_toolset(explicit_markup, toolset.first, release) &&
+                               !(is_unusable(explicit_markup, library.first, toolset.first))) {
+                               out[library.first][test_log.test_name][test_log.toolset].push_back(std::make_pair(&test_log, &runs.runner));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+std::size_t count_failures(const library_test_names_t& library) {
+    std::size_t result = 0;
+    BOOST_FOREACH(library_test_names_t::const_reference test, library) {
+        BOOST_FOREACH(library_test_names_t::mapped_type::const_reference toolset, test.second) {
+            result += toolset.second.size();
+        }
+    }
+    return result;
+}
+
+// okay
+void write_issues_list_reference_file(const std::string& out,
+                                      const std::string& source,
+                                      bool release,
+                                      const std::string& issues_list)
+{
+    html_writer document(out);
+    document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
+    document << "<html>\n";
+    document << "  <head>\n";
+    document << "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n";
+    document << "    <title>Boost regression unresolved issues: " << source << "</title>\n";
+    document << "  </head>\n";
+    document << "  <frameset cols=\"190px,*\" frameborder=\"0\" framespacing=\"0\" border=\"0\">\n";
+    document << "    <frame name=\"tocframe\" src=\"toc" << release_postfix(release) << ".html\" scrolling=\"auto\"/>\n";
+    document << "    <frame name=\"docframe\" src=\"" << issues_list << "\" scrolling=\"auto\"/>\n";
+    document << "  </frameset>\n";
+    document << "</html>\n";
+}
+
+void print_failure_cell(html_writer& document,
+                        const failures_markup_t& explicit_markup,
+                        const std::string& output_directory,
+                        const test_structure_t::test_log_t& test_log,
+                        const std::string& toolset,
+                        const std::string& runner,
+                        const std::string& release_postfix)
+{
+    std::string log_link = log_file_path(explicit_markup, test_log, runner, release_postfix);
+
+    const char* class_ = test_log.is_new?
+        "library-fail-unexpected-new" :
+        "library-fail-unexpected";
+    
+    document << "<td class=\"" << class_ << "\">\n";
+    document << "  <span>\n";
+    document << "    <a href=\"" << escape_uri(log_link) << "\" class=\"log-link\" target=\"_top\">\n";
+    document << "      " << escape_xml(toolset) << "\n";
+    document << "    </a>\n";
+    document << "  </span>\n";
+    document << "</td>\n";
+}
+
+void write_issues_list(const std::string& path,
+                       const failures_markup_t& explicit_markup,
+                       const std::string& output_directory,
+                       const libraries_t& libraries,
+                       const std::string& source,
+                       const boost::posix_time::ptime& run_date,
+                       const std::vector<std::string>& warnings,
+                       const std::string& purpose,
+                       bool release)
+{
+    //utils::log("Writing document " + path);
+    
+    const char* release_postfix = release? "_release" : "";
+
+    html_writer document(path);
+
+    document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n";
+      
+    document << "<html>\n";
+    document << "  <head>\n";
+    document << "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n";
+    document << "  </head>\n";
+    document << "  <body>\n";
+    document << "\n";
+    document << "    <h1 class=\"page-title\">\n";
+    document << "      Unresolved Issues: \n";
+    document << "      <a class=\"hover-link\" href=\"summary" << release_postfix << ".html\" target=\"_top\">" << source << "</a>\n";
+    document << "    </h1>\n";
+    document << "\n";
+
+    insert_report_header(document, run_date, warnings, purpose);
+
+    // Emit the index
+    document << "    <h2>Libraries with unresolved failures</h2>\n";
+    document << "    <div align=\"center\">\n";
+
+    BOOST_FOREACH(libraries_t::const_reference library, libraries) {
+        document << "      <a href=\"#" << escape_uri(library.first) << "\">\n";
+        document << "        " << escape_xml(library.first) << "\n";
+        document << "      </a>\n";
+    }
+
+    BOOST_FOREACH(libraries_t::const_reference library, libraries) {
+        std::string library_page(encode_path(library.first));
+        const library_test_names_t& library_test_names(library.second);
+        std::size_t failures = count_failures(library.second);
+
+        document << "      <h2>\n";
+        document << "        <a name=\"" << escape_uri(library.first) << "\"/>\n";
+        document << "        <a class=\"hover-link\" href=\"" << escape_uri(library_page)
+                 << release_postfix << ".html\" target=\"_top\">\n";
+        document << "        " << escape_xml(library.first) << " (" << failures
+                 << " failure" << (failures == 1? "":"s") << ")\n";
+        document << "        </a>\n";
+        document << "      </h2>\n";
+            
+        document << "      <table class=\"library-issues-table\" summary=\"issues\">\n";
+        document << "      <thead>\n";
+        document << "        <tr valign=\"middle\">\n";
+        document << "          <td class=\"head\">test</td>\n";
+        document << "          <td class=\"head\">failures</td>\n";
+        document << "        </tr>\n";
+        document << "      </thead>\n";
+        document << "      <tfoot>\n";
+        document << "        <tr valign=\"middle\">\n";
+        document << "          <td class=\"head\">test</td>\n";
+        document << "          <td class=\"head\">failures</td>\n";
+        document << "        </tr>\n";
+        document << "      </tfoot>\n";
+
+        document << "      <tbody>\n";
+
+        BOOST_FOREACH(library_test_names_t::const_reference test, library_test_names) {
+            const std::string& test_name = test.first;
+            const std::string& test_program = test.second.begin()->second.front().first->test_program;
+
+            document << "        <tr>\n";
+            document << "          <td class=\"test-name\">\n";
+            document << "            <a href=\"http://svn.boost.org/svn/boost/"
+                     << source << "/" << escape_uri(test_program) << "\" class=\"test-link\" target=\"_top\">\n";
+            document << "              " << escape_xml(test_name) << "\n";
+            document << "            </a>\n";
+            document << "          </td>\n";
+            document << "          <td class=\"failures-row\">\n";
+            document << "            <table summary=\"unexpected fail legend\" class=\"issue-box\">\n";
+            document << "              <tr class=\"library-row-single\">\n";
+
+            typedef library_test_names_t::mapped_type::const_reference toolset_t;
+            BOOST_FOREACH(toolset_t toolset, test.second) {
+                BOOST_FOREACH(const test_failure_t& failure, toolset.second) {
+                    print_failure_cell(document, explicit_markup, output_directory, *failure.first, toolset.first, *failure.second, release_postfix);
+                }
+            }
+
+            document << "              </tr>\n";
+            document << "            </table>\n";
+            document << "          </td>\n";
+            document << "        </tr>\n";
+        }
+        document << "      </tbody>\n";
+
+        document << "    </table>\n";
+    }
+    document << issues_legend;
+    document << make_tinyurl;
+    document << "  </body>\n";
+    document << "</html>\n";
+}
+
+// okay
+void write_issues_email(const std::string& path,
+                        const boost::posix_time::ptime& run_date,
+                        const std::string& source,
+                        const libraries_t& libraries)
+{
+    boost::filesystem::ofstream document(path);
+    std::cout << "Writing document " << path << std::endl;
+    //utils::log(boost::format("Writing document %s") % path);
+
+    std::size_t failing_tests = 0;
+    BOOST_FOREACH(libraries_t::const_reference library, libraries) {
+        failing_tests += count_failures(library.second);
+    }
+    
+    document << "Boost regression test failures\n"
+"------------------------------\n"
+"Report time: " << run_date << "\n"
+"\n"
+"This report lists all regression test failures on release platforms.\n"
+"\n"
+"Detailed report: \n"
+"        http://beta.boost.org/development/tests/" << source << "/developer/issues.html\n"
+"\n"
+<< failing_tests << " failure" << (failing_tests == 1? "" : "s")
+<< " in " << libraries.size() << " librar" << (libraries.size() == 1? "y" : "ies") << ":\n";
+
+    BOOST_FOREACH(libraries_t::const_reference library, libraries) {
+        document << "  " << library.first << " (" << count_failures(library.second) << ")\n";
+    }
+
+    BOOST_FOREACH(libraries_t::const_reference library, libraries) {
+
+        std::string library_page = encode_path(library.first);
+        document << "\n"
+        "|" << library.first << "|\n";
+
+        BOOST_FOREACH(libraries_t::mapped_type::const_reference test_name, library.second) {
+            document << "  " << test_name.first << ":";
+            BOOST_FOREACH(libraries_t::mapped_type::mapped_type::const_reference toolset, test_name.second) {
+                document << "  " << toolset.first;
+            }
+            document << "\n";
+        }
+    }
+}
+
+}
+
+void boost::regression::issues_list(const std::string& output_dir,
+                                    const test_structure_t& tests,
+                                    const failures_markup_t& explicit_markup,
+                                    bool release,
+                                    const std::string& source,
+                                    const boost::posix_time::ptime& run_date,
+                                    const std::vector<std::string>& warnings,
+                                    const std::string& purpose)
+{
+    ::libraries_t libraries;
+    failing_tests(tests, explicit_markup, release, libraries);
+    
+    std::string release_postfix_(release_postfix(release));
+    std::string issues_list("issues" + release_postfix_ + "_.html");
+
+    write_issues_list_reference_file(output_dir + "/issues.html", source, release, issues_list);
+    write_issues_list(output_dir + "/" + issues_list, explicit_markup, output_dir, libraries, source, run_date, warnings, purpose, release);
+
+    write_issues_email(output_dir + "/issues-email.txt",
+                       run_date,
+                       source,
+                       libraries);
+}
Added: trunk/tools/regression/src/report/issues_page.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/issues_page.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,31 @@
+// issues_page.hpp
+//
+// Copyright (c) 2010
+// Steven Watanabe
+//
+// Distributed under 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)
+
+#include "xml.hpp"
+
+#include <boost/filesystem/path.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+
+#include <string>
+#include <vector>
+
+namespace boost {
+namespace regression {
+
+void issues_list(const std::string& output_dir,
+                 const test_structure_t& tests,
+                 const failures_markup_t& explicit_markup,
+                 bool release,
+                 const std::string& source,
+                 const boost::posix_time::ptime& run_date,
+                 const std::vector<std::string>& warnings,
+                 const std::string& purpose);
+
+}
+}
\ No newline at end of file
Added: trunk/tools/regression/src/report/links_page.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/links_page.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,369 @@
+// Copyright MetaCommunications, Inc. 2003-2006.
+// Copyright Steven Watanabe 2010
+//
+// Distributed under 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)
+
+#include "links_page.hpp"
+#include "xml.hpp"
+#include "common.hpp"
+#include "html_writer.hpp"
+#include "html.hpp"
+
+#include <boost/date_time/posix_time/ptime.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/foreach.hpp>
+#include <string>
+#include <vector>
+
+using namespace boost::regression;
+
+namespace {
+
+void links_page(const boost::posix_time::ptime& run_date,
+                const failures_markup_t& explicit_markup,
+                const std::string& runner_id,
+                const std::string& revision,
+                const boost::posix_time::ptime& timestamp,
+                const std::string& library_name,
+                const std::string& toolset_name,
+                const std::string& test_name,
+                const std::vector<test_structure_t::test_log_t>& test_logs);
+void write_variants_reference_file(const std::string& path,
+                                   const std::string& variants_file_path,
+                                   const std::string release_postfix);
+std::string output_page_header(node_ptr test_log, const std::string& runner_id);
+void write_variants_file(const boost::posix_time::ptime& run_date,
+                         const failures_markup_t& explicit_markup,
+                         const std::string& path,
+                         const std::vector<test_structure_t::test_log_t>& test_logs,
+                         const std::string& runner_id,
+                         const std::string& revision,
+                         const boost::posix_time::ptime& timestamp);
+void write_test_result_file(const boost::posix_time::ptime& run_date,
+                            const failures_markup_t& explicit_markup,
+                            const std::string& path,
+                            const test_structure_t::test_log_t& test_log,
+                            const std::string& runner_id,
+                            const std::string& revision,
+                            const boost::posix_time::ptime& timestamp);
+void write_test_results_reference_file(const std::string& path, const std::string& log_file_path);
+
+// requires: revision must be a SVN revision.  i.e. of the form nnnnn
+void links_page(const boost::posix_time::ptime& run_date,
+                const failures_markup_t& explicit_markup,
+                const std::string& runner_id,
+                const std::string& revision,
+                const boost::posix_time::ptime& timestamp,
+                const std::string& library_name,
+                const std::string& toolset_name,
+                const std::string& test_name,
+                const std::vector<test_structure_t::test_log_t>& test_logs) {
+    //utils::log("Processing test \"" + runner_id + "/" + library_name + "/" + test_name + "/" + toolset_name + "\"");
+                    
+    const char* postfixes[] = {"", "_release"};
+    const char* dirs[] = { "developer", "user" };
+
+    if(test_logs.size() > 1) {
+        // utils::log("  Processing variants");
+
+        std::string variants_file_path = output_file_path(runner_id + "-" + library_name + "-" + toolset_name + "-" + test_name + "-variants");
+
+        write_variants_file(run_date, explicit_markup, variants_file_path, test_logs, runner_id, revision, timestamp);
+
+        BOOST_FOREACH(const std::string& release_postfix, postfixes) {
+            BOOST_FOREACH(const std::string& directory, dirs) {
+                std::string variants__file_path = directory + "/" + (encode_path(runner_id + "-" + library_name + "-" + toolset_name + "-" + test_name + "-variants_" + release_postfix) + ".html");
+                write_variants_reference_file(variants__file_path, "../" + variants_file_path, release_postfix);
+            }
+        }
+    }
+
+    BOOST_FOREACH(const test_structure_t::test_log_t& test_log, test_logs) {
+        //utils::log("  Processing test-log");
+
+        if(show_output(explicit_markup, test_log)) {
+            std::string log_path = log_file_path(explicit_markup, test_log, runner_id);
+            write_test_result_file(run_date, explicit_markup, log_path, test_log, runner_id, revision, timestamp);
+            
+            BOOST_FOREACH(const std::string& release_postfix, postfixes) {
+                BOOST_FOREACH(const std::string& directory, dirs) {
+                    std::string reference_file_path = directory + "/" + log_file_path(explicit_markup, test_log, runner_id, release_postfix);
+                    write_test_results_reference_file(reference_file_path, log_path);
+                }
+            }
+        }
+    }
+}
+
+// requires: path must be a valid file path.
+// requires: variants_file_path must be the path to the variants file relative to path
+void write_variants_reference_file(const std::string& path,
+                                   const std::string& variants_file_path,
+                                   const std::string release_postfix)
+{
+    //utils::log("    Writing variants reference file %s" % path);
+
+    html_writer document(path);
+    
+    document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                "<html>\n"
+                "    <head>\n"
+                "        <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+                "    </head>\n"
+                "    <frameset cols=\"190px,*\" frameborder=\"0\" framespacing=\"0\" border=\"0\">\n"
+                "        <frame name=\"tocframe\" src=\"toc" << release_postfix  << ".html\" scrolling=\"auto\"/>\n"
+                "        <frame name=\"docframe\" src=\"" << escape_uri(variants_file_path) << "\" scrolling=\"auto\"/>\n"
+                "    </frameset>\n"
+                "</html>\n";
+}
+
+// okay. result is unconstrained
+std::string output_page_header(const test_structure_t::test_log_t& test_log, const std::string& runner_id) {
+    if(test_log.test_name != "") {
+        return runner_id + " - " + test_log.library + " - " + test_log.test_name + " / " + test_log.toolset;
+    } else {
+        return test_log.target_directory;
+    }
+}
+
+// requires revision is an SVN revision #
+// requires path is a valid path
+void write_variants_file(const boost::posix_time::ptime& run_date,
+                         const failures_markup_t& explicit_markup,
+                         const std::string& path,
+                         const std::vector<test_structure_t::test_log_t>& test_logs,
+                         const std::string& runner_id,
+                         const std::string& revision,
+                         const boost::posix_time::ptime& timestamp)
+{
+    //utils::log("    Writing variants file " + path.string());
+    html_writer document(path);
+
+    std::string component = output_page_header(test_logs[0], runner_id);
+    int age = timestamp_difference(timestamp, run_date);
+
+    document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                "<html>\n"
+                "    <head>\n"
+                "        <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+                "        <title>Test output: " << escape_xml(component) << "</title>\n"
+                "    </head>\n"
+                "    <body>\n"
+                "        <div class=\"log-test-header\">\n"
+                "            <div class=\"log-test-title\">\n"
+                "                Test output: " << escape_xml(component) << "\n"
+                "            </div>\n"
+                "            <div><span class=\"timestamp-" << age << "\">\n"
+                "                Rev " << revision << " /\n"
+                "                " << format_timestamp(timestamp) << "\n"
+                "            </span></div>\n"
+                "        </div>\n"
+                "\n"
+                "        <div>\n"
+                "            <b>Report Time: </b> " << format_timestamp(run_date) << "\n"
+                "        </div>\n"
+                "\n"
+                "        <p>Output by test variants:</p>\n"
+                "        <table>\n";
+
+    BOOST_FOREACH(const test_structure_t::test_log_t& log, test_logs) {
+
+        document << "            <tr>\n"
+                    "                <td>\n";
+
+        std::string log_file = log_file_path(explicit_markup, log, runner_id);
+        if(!log_file.empty()) {
+
+            document << "                    <a href=\"../" << escape_uri(log_file) << "\">\n"
+                        "                        " << escape_xml(log.target_directory) << "\n"
+                        "                    </a>\n";
+
+        } else {
+
+            document << "                    " << escape_xml(log.target_directory) << "\n";
+
+        }
+
+            document << "                </td>\n"
+                        "            </tr>\n";
+                     
+    }
+
+    document << "        </table>\n"
+                "    </body>\n"
+                "</html>\n";
+}
+
+// okay
+const test_structure_t::target_t* lookup_target(const test_structure_t::test_log_t& test_log, const std::string& name) {
+    boost::unordered_map<std::string, test_structure_t::target_t>::const_iterator pos = test_log.targets.find(name);
+    if(pos != test_log.targets.end()) {
+        return &pos->second;
+    } else {
+        return 0;
+    }
+}
+
+// requires: path is a valid path
+// requires: revision is an SVN revision
+void write_test_result_file(const boost::posix_time::ptime& run_date,
+                            const failures_markup_t& explicit_markup,
+                            const std::string& path,
+                            const test_structure_t::test_log_t& test_log,
+                            const std::string& runner_id,
+                            const std::string& revision,
+                            const boost::posix_time::ptime& timestamp)
+{
+    //utils::log(boost::format("    Writing log file document %s") % path);
+
+    html_writer document(path);
+    
+    std::string component = output_page_header(test_log, runner_id);
+    int age = timestamp_difference(timestamp, run_date);
+    
+    document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                "<html>\n";
+
+    document << "    <head>\n"
+                "        <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+                "        <title>Test output: " << escape_xml(component) << "</title>\n"
+                "    </head>\n";
+
+    document << "    <body>\n"
+                "        <div class=\"log-test-header\">\n"
+                "            <div class=\"log-test-title\">\n"
+                "                Test output: " << escape_xml(component) << "\n"
+                "            </div>\n"
+                "            <div><span class=\"timestamp-" << age << "\">\n"
+                "                Rev " << revision << " /\n"
+                "                " << format_timestamp(timestamp) << "\n"
+                "            </span></div>\n"
+                "        </div>\n";
+
+    document << "        <div>\n"
+                "            <b>Report Time: </b> " << format_timestamp(run_date) << "\n"
+                "        </div>\n";
+    
+    if(!test_log.notes.empty()) {
+
+        document << "        <p>\n"
+                    "            <div class=\"notes-title\">Notes</div>\n";
+
+        show_notes(document, test_log.notes, explicit_markup);
+
+        document << "        </p>\n";
+
+    }
+
+    if(const test_structure_t::target_t* compile = lookup_target(test_log, "compile")) {
+        const char* compile_result = compile->result? "succeed" : "fail";
+        document << "        <p>\n";
+        document << "            <div class=\"log-compiler-output-title\">Compile [" << escape_xml(compile->timestamp) << "]:"
+                                 " <span class=\"output-" << compile_result << "\">" << compile_result << "</span></div>\n";
+        document << "            <pre>\n";
+        write_contents(document, compile->contents, true);
+        document << "            </pre>\n";
+        document << "        </p>\n";
+    }
+
+    if(const test_structure_t::target_t* link = lookup_target(test_log, "link")) {
+        const char* link_result = link->result? "succeed" : "fail";
+        document << "        <p>\n";
+        document << "            <div class=\"log-linker-output-title\">Link [" << escape_xml(link->timestamp) << "]:"
+                                 " <span class=\"output-" << link_result << "\">" << link_result << "</span></div>\n";
+        document << "            <pre>\n";
+        write_contents(document, link->contents, true);
+        document << "            </pre>\n";
+        document << "        </p>\n";
+    }
+
+    if(const test_structure_t::target_t* lib = lookup_target(test_log, "lib")) {
+        const char* lib_result = lib->result? "succeed" : "fail";
+        std::string lib_name(lib->contents->value(), lib->contents->value_size());
+        document << "        <p>\n";
+        document << "            <div class=\"log-linker-output-title\">Lib [" << escape_xml(lib->timestamp) << "]:"
+                                 " <span class=\"output-" << lib_result << "\">" << lib_result << "</span></div>\n";
+        document << "            <p>\n";
+        document << "                See <a href=\"" << escape_uri(encode_path(runner_id + "-" + lib_name)) << ".html\">\n";
+        document << "                " << escape_xml(lib_name) << "\n";
+        document << "                </a>\n";
+        document << "            </p>\n";
+        document << "        </p>\n";
+    }
+         
+    if(const test_structure_t::target_t* run = lookup_target(test_log, "run")) {
+        const char* run_result = run->result? "succeed" : "fail";
+        document << "        <p>\n";
+        document << "            <div class=\"log-linker-output-title\">Run [" << escape_xml(run->timestamp) << "]:"
+                                 " <span class=\"output-" << run_result << "\">" << run_result << "</span></div>\n";
+        document << "            <pre>\n";
+        write_contents(document, run->contents, true);
+        document << "            </pre>\n";
+        document << "        </p>\n";
+    }
+
+    document << make_tinyurl;
+
+    document << "    </body>\n";
+    document << "</html>\n";
+}
+
+// requires path is a valid path
+// requires: log_file_path is the location of the log file relative to path
+void write_test_results_reference_file(const std::string& path, const std::string& log_file_path)
+{
+    html_writer document(path);
+    
+    document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                "<html>\n"
+                "    <head>\n"
+                "        <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+                "    </head>\n"
+                "    <frameset cols=\"190px,*\" frameborder=\"0\" framespacing=\"0\" border=\"0\">\n"
+                "        <frame name=\"tocframe\" src=\"../toc.html\" scrolling=\"auto\"/>\n"
+                "        <frame name=\"docframe\" src=\"../../" << escape_uri(log_file_path) << "\" scrolling=\"auto\"/>\n"
+                "    </frameset>\n"
+                "</html>\n";
+}
+
+}
+
+// okay
+void boost::regression::links_page(
+    const boost::posix_time::ptime& run_date,
+    const failures_markup_t& explicit_markup,
+    const test_structure_t::run_t& test_run)
+{
+    BOOST_FOREACH(const test_structure_t::toolset_group_t::const_reference toolset, test_run.toolsets) {
+        BOOST_FOREACH(const test_structure_t::toolset_t::const_reference library, toolset.second) {
+            BOOST_FOREACH(const test_structure_t::library_t::const_reference test_case, library.second) {
+                ::links_page(run_date,
+                             explicit_markup,
+                             test_run.runner,
+                             test_run.revision,
+                             test_run.timestamp,
+                             library.first,
+                             toolset.first,
+                             test_case.first,
+                             test_case.second);
+            }
+        }
+    }
+    BOOST_FOREACH(const test_structure_t::toolset_group_t::const_reference toolset, test_run.non_test_case_targets) {
+        BOOST_FOREACH(const test_structure_t::toolset_t::const_reference library, toolset.second) {
+            BOOST_FOREACH(const test_structure_t::library_t::const_reference test_case, library.second) {
+                ::links_page(run_date,
+                             explicit_markup,
+                             test_run.runner,
+                             test_run.revision,
+                             test_run.timestamp,
+                             library.first,
+                             toolset.first,
+                             test_case.first,
+                             test_case.second);
+            }
+        }
+    }
+}
Added: trunk/tools/regression/src/report/links_page.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/links_page.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,26 @@
+// links_page.hpp
+//
+// Copyright (c) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanyiong file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef LINKS_PAGE_HPP_INCLUDED
+#define LINKS_PAGE_HPP_INCLUDED
+
+#include "xml.hpp"
+#include <boost/filesystem/path.hpp>
+
+namespace boost {
+namespace regression {
+
+void links_page(
+    const boost::posix_time::ptime& run_date,
+    const failures_markup_t& explicit_markup,
+    const test_structure_t::run_t& test_run);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/produce_expected_results.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/produce_expected_results.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,28 @@
+// Copyright MetaCommunications, Inc. 2003-2005.
+// Copyright Steven Watanabe 2013
+//
+// Distributed under 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)
+
+#include "produce_expected_results.hpp"
+#include "html_writer.hpp"
+#include <iostream>
+
+void boost::regression::produce_expected_results(const test_structure_t& tests) {
+    std::cout << "Warning: expected results not implemented" << std::endl;
+    return;
+
+    html_writer document("expected_results.xml");
+    document << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+    document << "<root>\n";
+    document << "  <expected-failures>\n";
+#if 0
+    foreach test-log
+    <xsl:if test="meta:is_test_log_a_test_case(.)">
+        <test-result library="{@library}" test-name="{@test-name}" toolset="{@toolset}" result="{@result}" />
+    </xsl:if>
+#endif
+    document << "  </expected-failures>\n";
+    document << "</root>\n";
+}
Added: trunk/tools/regression/src/report/produce_expected_results.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/produce_expected_results.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,22 @@
+// result_page.cpp
+//
+// Copyright Steven Watanabe 2013
+//
+// Distributed under 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 BOOST_REGRESSION_PRODUCE_EXPECTED_RESULTS_HPP
+#define BOOST_REGRESSION_PRODUCE_EXPECTED_RESULTS_HPP
+
+#include "xml.hpp"
+
+namespace boost {
+namespace regression {
+    
+void produce_expected_results(const test_structure_t& tests);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/result_page.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/result_page.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,513 @@
+// result_page.cpp
+//
+// Copyright MetaCommunications, Inc. 2003-2007.
+// Copyright Steven Watanabe 2010-2011
+//
+// Distributed under 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)
+
+#include "result_page.hpp"
+#include "common.hpp"
+#include "html.hpp"
+#include "html_writer.hpp"
+#include "xml.hpp"
+#include <boost/foreach.hpp>
+#include <boost/unordered_map.hpp>
+#include <set>
+#include <map>
+#include <string>
+#include <vector>
+#include <utility>
+#include <iostream>
+#include <fstream>
+
+using namespace boost::regression;
+
+namespace {
+
+// safe: no assumptions, no unconstrained output
+void test_type_col(html_writer& document, const std::string& test_type) {
+    document << "<td class=\"test-type\">\n";
+    document << "    <a href=\"http://www.boost.org/status/compiler_status.html#Understanding\" class=\"legend-link\" target=\"_top\">";
+
+    if(test_type == "run_pyd") {
+        document << "r";
+    } else if(test_type == "run_mpi") {
+        document << "r";
+    } else if(test_type == "run") {
+        document << "r";
+    } else if(test_type == "run_fail") {
+        document << "rf";
+    } else if(test_type == "compile") {
+        document << "c";
+    } else if(test_type == "compile_fail") {
+        document << "cf";
+    } else if(test_type == "link") {
+        document << "l";
+    } else if(test_type == "link_fail") {
+        document << "lf";
+    } else {
+        throw std::runtime_error("Incorrect test type \"" + test_type + "\"");
+    }
+
+    document << "    </a>\n";
+    document << "</td>\n";
+}
+
+// category/name
+typedef std::pair<std::string, std::string> test_case_id_t;
+// runner/toolset
+typedef std::pair<std::string, std::string> test_toolset_id_t;
+
+typedef std::vector<const test_structure_t::test_log_t*> test_log_group_t;
+typedef boost::unordered_map<test_toolset_id_t, test_log_group_t> test_logs_by_run_t;
+typedef std::map<test_case_id_t, test_logs_by_run_t> test_logs_t;
+
+// requires: result contains no HTML special characters
+// requires: log_link must not contain a '/' derived from the input (This won't actually break anything, though)
+void insert_cell_link(html_writer& document, const std::string& result, const std::string& log_link) {
+    if(log_link != "") {
+        document << "  "
+                    "<a href=\"" << escape_uri(log_link) << "\" class=\"log-link\" target=\"_top\">"
+                 << result <<
+                    "</a>"
+                    "  ";
+    } else {
+        document << "  " << result << "  ";
+    }
+}
+     
+// requires:
+void insert_cell_developer(html_writer& document,
+                           const failures_markup_t& explicit_markup,
+                           bool release,
+                           const std::string& library,
+                           const std::string& test_name,
+                           const std::string& runner,
+                           const std::string& toolset,
+                           const test_log_group_t& test_logs) {
+    std::string class_ = "library-" + result_cell_class(explicit_markup, library, toolset, test_logs);
+
+    std::string cell_link = (test_logs.size() > 1)?
+        encode_path(runner + "-" + library + "-" + toolset + "-" + test_logs.front()->test_name + "-variants_" + release_postfix(release)) + ".html" :
+        (test_logs.empty())?
+        std::string("") :
+        log_file_path(explicit_markup, *test_logs.front(), runner, release_postfix(release));
+
+    document << "<td class=\"" << class_ << "\" title=\"" << escape_xml(test_name) << "/" << escape_xml(toolset) << "\">\n";
+
+    if(is_unusable(explicit_markup, library, toolset)) {
+        insert_cell_link(document, "n/a", cell_link);
+    } else if(test_logs.empty()) {
+        document << "    \n";
+    } else {
+        BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+            if(!log->result && log->status) {
+                insert_cell_link(document, (log->expected_reason != "")? "fail?" : "fail*", cell_link);
+                goto done;
+            }
+        }
+        BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+            if(!log->result && !log->status) {
+                insert_cell_link(document, "fail", cell_link);
+                goto done;
+            }
+        }
+        insert_cell_link(document, "pass", cell_link);
+    }
+done:
+    document << "</td>\n";
+}
+
+// requires: 
+void insert_cell_user(html_writer& document,
+                      const failures_markup_t& explicit_markup,
+                      bool release,
+                      const std::string& library,
+                      const std::string& test_name,
+                      const std::string& runner,
+                      const std::string& toolset,
+                      const test_log_group_t& test_logs) {
+    std::string class_ = "library-" + result_cell_class(explicit_markup, library, toolset, test_logs);
+
+    std::string cell_link = (test_logs.size() > 1)?
+        encode_path(runner + "-" + library + "-" + toolset + "-" + test_logs.front()->test_name + "-variants_" + release_postfix(release)) + ".html" :
+        (test_logs.empty())?
+        std::string("") :
+        log_file_path(explicit_markup, *test_logs.front(), runner, release_postfix(release));
+
+    document << "<td class=\"" << class_ << " user-" << class_ << "\" title=\"" << escape_xml(test_name) << "/" << escape_xml(toolset) << "\">\n";
+
+    if(is_unusable(explicit_markup, library, toolset)) {
+        insert_cell_link(document, "unusable", cell_link);
+    } else if(test_logs.empty()) {
+        document << "    \n";
+    } else {
+        BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+            if(!log->result && log->status) {
+                insert_cell_link(document, (log->expected_reason != "")? "fail?" : "fail*", cell_link);
+                goto done;
+            }
+        }
+        BOOST_FOREACH(test_log_group_t::value_type log, test_logs) {
+            if(!log->result && !log->status) {
+                insert_cell_link(document, "fail", cell_link);
+                goto done;
+            }
+        }
+        insert_cell_link(document, "pass", cell_link);
+    }
+done:
+    document << "</td>\n";
+}
+
+// requires: line_mod should be from an enumerated set
+// requires: source is a branch of svn
+// requires: mode = developer | user
+void insert_test_line(html_writer& document,
+                      const failures_markup_t& explicit_markup,
+                      bool release,
+                      const std::string& library,
+                      test_logs_t::const_reference test_results,
+                      const std::vector<std::pair<std::string, std::string> >& all_toolsets,
+                      const std::string& line_mod,
+                      const std::string& source,
+                      const std::string& mode) {
+    // This is guaranteed to exist because of the way the nested maps are created
+    const test_structure_t::test_log_t * first_log = (*test_results.second.begin()).second.front();
+    std::string test_program(first_log->test_program);
+
+    std::string test_header =
+        "<td class=\"test-name\">\n"
+        "    <a href=\"http://svn.boost.org/svn/boost/" + source + "/" + escape_uri(test_program) + "\" class=\"test-link\" target=\"_top\">\n"
+        "        " + escape_xml(test_results.first.second) + "\n" // FIXME: sanitize test name
+        "    </a>\n"
+        "</td>\n";
+
+    document << "<tr class=\"library-row" << line_mod << "\">\n"
+             << test_header;
+
+    test_log_group_t empty_test_log;
+    test_type_col(document, first_log->test_type);
+    BOOST_FOREACH(const test_toolset_id_t& run, all_toolsets) {
+        const std::string& toolset = run.second;
+        const std::string& runner = run.first;
+
+        test_logs_by_run_t::const_iterator pos = test_results.second.find(run);
+        
+        const test_log_group_t* test_result_for_toolset = 
+            (pos != test_results.second.end())?
+            &pos->second :
+            &empty_test_log;
+
+        if(mode == "user") {
+            insert_cell_user(document, explicit_markup, release, library, test_results.first.second, runner, toolset, *test_result_for_toolset);
+        } else {
+            insert_cell_developer(document, explicit_markup, release, library, test_results.first.second, runner, toolset, *test_result_for_toolset);
+        }
+    }
+
+    document << test_header
+             << "</tr>\n";
+}
+
+// requires: source is a branch of svn
+// requires: mode = developer | user
+void insert_test_section(html_writer& document,
+                         const test_structure_t& test_structure,
+                         const failures_markup_t& explicit_markup,
+                         bool release,
+                         const std::string& library,
+                         const test_logs_t& logs,
+                         const std::vector<std::pair<std::string, std::string> >& all_toolsets,
+                         const std::string& source,
+                         const std::string& mode) {
+    std::size_t category_span = 3;
+    BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, test_structure.platforms) {
+        BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+            category_span += (run.toolsets.size());
+        }
+    }
+
+    for(test_logs_t::const_iterator pos = logs.begin(), end = logs.end(); pos != end; ++pos) {
+        std::string test_name = pos->first.second;
+        bool category_start = (pos == logs.begin()) || (pos->first.first != boost::prior(pos)->first.first);
+        bool category_end   = (boost::next(pos) == end) || (pos->first.first != boost::next(pos)->first.first);
+
+        std::string line_mod =
+            (category_start && category_end)? "-single" :
+            category_start? "-first" :
+            category_end? "-last" :
+            "";
+
+        if(category_start && pos->first.first != "0") {
+            document << "<tr>\n"
+                        "    <td class=\"library-test-category-header\" colspan=\"" << category_span << "\" align=\"center\">\n"
+                        "        " << escape_xml(pos->first.first) << "\n"
+                        "    </td>\n"
+                        "</tr>\n";
+        }
+
+        insert_test_line(document, explicit_markup, release, library, *pos, all_toolsets, line_mod, source, mode);
+    }
+}
+
+}
+
+// requires: mode = developer | user
+// requires: source = Boost SVN branch name
+void boost::regression::result_page(const test_structure_t& tests,
+                                    const failures_markup_t& explicit_markup,
+                                    bool release,
+                                    const std::string& source,
+                                    const boost::posix_time::ptime& run_date,
+                                    const std::vector<std::string>& warnings,
+                                    const std::string& mode,
+                                    const boost::filesystem::path& comment_file)
+{
+    // skip debug.xml
+
+    std::string index_path("index" + release_postfix(release) + "_.html");
+        
+    {
+
+    std::cout << "Writing document " << "index" << release_postfix(release) << ".html" << std::endl;
+
+    html_writer index(mode + "/" + "index" + release_postfix(release) + ".html");
+    index << "<head>\n"
+             "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+             "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+             "    <title>Boost regression: " << source << "</title>\n"
+             "</head>\n"
+             "<frameset cols=\"190px,*\" frameborder=\"0\" framespacing=\"0\" border=\"0\">\n"
+             "    <frame name=\"tocframe\" src=\"toc" << release_postfix(release) << ".html\" scrolling=\"auto\"/>\n"
+             "    <frame name=\"docframe\" src=\"" << index_path << "\" scrolling=\"auto\"/>\n"
+             "</frameset>\n";
+    }
+
+    std::cout << "Writing document " << index_path << std::endl;
+
+    {
+        html_writer index(mode + "/" + index_path);
+        index << "<html>\n"
+                 "<head>\n"
+                 "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+                 "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+                 "</head>\n"
+                 "<body>\n"
+                 "\n"
+                 "    <img border=\"0\" src=\"http://www.boost.org/boost.png\" width=\"277\" height=\"86\" align=\"right\" alt=\"Boost logo\"></img>\n"
+                 "\n"
+                 "    <h1 class=\"page-title\">\n"
+                          << mode << " report: "
+                 "        <a class=\"hover-link\" href=\"summary.html\" target=\"_top\">" << source << "</a>\n"
+                 "    </h1>\n"
+                 "\n";
+
+        std::string purpose = (mode == "user")?
+            "The purpose of this report is to help a user to find out whether a particular library "
+            "works on the particular compiler(s). For SVN \"health report\", see "
+            "       <a href=\"../developer/index.html\" target=\"_top\">developer summary</a>."
+            :
+            "Provides Boost developers with visual indication of the SVN \"health\". For user-level "
+            "report, see <a href=\"../user/index.html\" target=\"_top\">user summary</a>.";
+
+        insert_report_header(index, run_date, warnings, purpose);
+
+        index << "    <div class=\"comment\">\n";
+        if(comment_file != "") {
+            std::ifstream comment(comment_file.string().c_str());
+            if(!comment) {
+                throw std::ios_base::failure("Could not open file " + comment_file.string());
+            }
+            std::string comment_data(std::istreambuf_iterator<char>(comment.rdbuf()), std::istreambuf_iterator<char>());
+            index << comment_data;
+        }
+
+        index << "</body>\n";
+        index << "</html>\n";
+    }
+
+    std::set<std::string> libraries;
+    get_libraries(tests, libraries);
+
+    if(libraries.size() > 1) {
+        std::string toc_path("toc" + release_postfix(release) + ".html");
+        
+        std::cout << "Writing document " << toc_path << std::endl;
+
+        html_writer toc(mode + "/" + toc_path);
+
+        toc << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+            << "<html>\n"
+            << "<head>\n"
+            << "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+            << "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\"/>\n"
+            << "</head>\n"
+            << "<body class=\"" << mode << "-toc\">\n"
+            << "    <div class=\"toc-header-entry\">\n"
+            << "        <a href=\"index" << release_postfix(release) << ".html\" class=\"toc-entry\" target=\"_top\">Report info</a>\n"
+            << "    </div>\n"
+            << "    <div class=\"toc-header-entry\">\n"
+            << "        <a href=\"summary" << release_postfix(release) << ".html\" class=\"toc-entry\" target=\"_top\">Summary</a>\n"
+            << "    </div>\n";
+
+        if(mode == "developer") {
+            toc << "    <div class=\"toc-header-entry\">\n"
+                   "        <a href=\"issues.html\" class=\"toc-entry\" target=\"_top\">Unresolved issues</a>\n"
+                   "    </div>\n";
+        }
+
+        toc << "    <div class=\"toc-header-entry\">\n";
+
+        insert_view_link(toc, "index", "toc-entry", release);
+
+        toc << "    </div>\n";
+
+        toc << "    <hr/>\n";
+
+        BOOST_FOREACH(const std::string& library, libraries) {
+            std::string library_page(encode_path(library));
+            toc << "    <div class=\"toc-entry\">\n"
+                   "        <a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"toc-entry\" target=\"_top\">\n"
+                   "            " << escape_xml(library) <<  "\n"
+                   "        </a>\n"
+                   "    </div>\n";
+        }
+
+        toc << "</body>\n"
+               "</html>\n";
+    }
+
+    BOOST_FOREACH(const std::string& library, libraries) {
+        if(show_library(explicit_markup, library, release)) {
+            
+            std::string library_results(encode_path(library) + release_postfix(release) + "_.html");
+            std::string library_page(encode_path(library) + release_postfix(release) + ".html");
+
+            std::cout << "Writing document " << library_page << std::endl;
+
+            {
+                html_writer document(mode + "/" + library_page);
+
+                document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                            "<html>\n"
+                            "<head>\n"
+                            "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+                            "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\"/>\n"
+                            "    <title>Boost regression: " << escape_xml(library) << "/" << source << "</title>\n"
+                            "</head>\n"
+                            "<frameset cols=\"190px,*\" frameborder=\"0\" framespacing=\"0\" border=\"0\">\n"
+                            "<frame name=\"tocframe\" src=\"toc" << release_postfix(release) << ".html\" scrolling=\"auto\"/>\n"
+                            "<frame name=\"docframe\" src=\"" << escape_uri(library_results) << "\" scrolling=\"auto\"/>\n"
+                            "</frameset>\n"
+                            "</html>\n";
+            }
+
+            std::cout << "Writing document " << library_results << std::endl;
+            
+            {
+                html_writer document(mode + "/" + library_results);
+
+                document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                            "<html>\n"
+                            "<head>\n"
+                            "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+                            "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\" />\n"
+                            "</head>\n"
+                            "\n"
+                            "<body>\n";
+
+                insert_page_links(document, encode_path(library), release, alternate_mode(mode));
+
+                document << "<h1 class=\"page-title\">\n"
+                            "    <a class=\"hover-link\" name=\"" << escape_xml(library) << "\" href=\"http://www.boost.org/libs/" << escape_uri(library) << "\" target=\"_top\">"
+                         << escape_xml(library) << "\n"
+                            "</a>"
+                            "/"
+                            "<a class=\"hover-link\" href=\"summary.html\" target=\"_top\">" << source << "</a>\n"
+                            "</h1>\n";
+
+                insert_report_header(document, run_date, warnings);
+
+                // toolset/note/index
+                boost::unordered_map<std::string, std::size_t> library_marks;
+                std::vector<node_ptr> notes;
+                get_unusable(explicit_markup, library, tests, library_marks, notes);
+
+                document << "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=\"library-table\" width=\"1%\" summary=\"Library results\">\n"
+                            "    <thead>\n";
+
+                insert_runners_rows(document, "details", "top", tests, run_date); // okay
+                insert_toolsets_row(document, tests, explicit_markup, "details", run_date, library, library_marks);
+                      
+                document << "    </thead>\n"
+                            "    <tfoot>\n";
+                
+                insert_toolsets_row(document, tests, explicit_markup, "details", run_date, library, library_marks);
+                insert_runners_rows(document, "details", "bottom", tests, run_date);
+                document << "    </tfoot>\n"
+                            "    <tbody>\n";
+
+                test_logs_t lib_tests;
+                std::vector<std::pair<std::string, std::string> > all_toolsets;
+                BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, tests.platforms) {
+                    BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                        BOOST_FOREACH(test_structure_t::toolset_group_t::const_reference toolset, run.toolsets) {
+                            all_toolsets.push_back(std::make_pair(run.runner, toolset.first));
+                            test_structure_t::toolset_t::const_iterator pos = toolset.second.find(library);
+                            if(pos != toolset.second.end()) {
+                                BOOST_FOREACH(test_structure_t::library_t::const_reference test_case, pos->second) {
+                                    test_log_group_t test_logs;
+                                    BOOST_FOREACH(test_structure_t::test_case_t::const_reference log, test_case.second) {
+                                        if(is_test_log_a_test_case(log)) {
+                                            test_logs.push_back(&log);
+                                        }
+                                    }
+                                    if(!test_logs.empty()) {
+                                        std::string category = test_logs.front()->category;
+                                        lib_tests[std::make_pair(category, test_case.first)][std::make_pair(run.runner, toolset.first)] = test_logs;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                insert_test_section(document, tests, explicit_markup, release, library, lib_tests, all_toolsets, source, mode);
+
+                document << "    </tbody>\n"
+                            "</table>\n";
+
+                if(!notes.empty()) {
+                    document << "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"library-library-notes\" summary=\"library notes\">\n";
+                    for(std::size_t i = 0; i < notes.size(); ++i) {
+                        document << "<tr class=\"library-library-note\">\n"
+                                    "    <td valign=\"top\" width=\"3em\">\n"
+                                    "        <a name=\"" << escape_uri(library) << "-note-" << (i + 1) << "\">\n"
+                                    "            <span class=\"super\">" << (i + 1) << "</span>\n"
+                                    "        </a>\n"
+                                    "    </td>\n"
+                                    "    <td>\n";
+                        std::string refid;
+                        lookup_attr(notes[i], "refid", refid);
+                        show_note(document, notes[i], refid, explicit_markup);
+                        document << "    </td>\n"
+                                    "</tr>\n";
+                    }
+                    document << "</table>\n";
+                }
+
+                document << "<div id=\"legend\">\n"
+                         << (mode == "developer"? library_developer_legend : library_user_legend) << "\n"
+                            "</div>\n";
+
+                insert_page_links(document, encode_path(library), release, alternate_mode(mode));
+
+                document << "</body>\n";
+                document << "</html>\n";
+            }
+        }
+    }
+}
Added: trunk/tools/regression/src/report/result_page.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/result_page.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,29 @@
+// result_page.cpp
+//
+// Copyright MetaCommunications, Inc. 2003-2007.
+// Copyright Steven Watanabe 2010-2011
+//
+// Distributed under 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)
+
+#include <boost/filesystem/path.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include <string>
+#include <vector>
+#include "xml.hpp"
+
+namespace boost {
+namespace regression {
+
+void result_page(const test_structure_t& tests,
+                 const failures_markup_t& explicit_markup,
+                 bool release,
+                 const std::string& source,
+                 const boost::posix_time::ptime& run_date,
+                 const std::vector<std::string>& warnings,
+                 const std::string& mode,
+                 const boost::filesystem::path& comment_file);
+
+}
+}
Added: trunk/tools/regression/src/report/runners.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/runners.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,53 @@
+// Copyright MetaCommunications, Inc. 2003-2004.
+//
+// Distributed under 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)
+
+#include "runners.hpp"
+#include "html_writer.hpp"
+#include "common.hpp"
+#include <boost/foreach.hpp>
+#include <iostream>
+
+void boost::regression::runners(const test_structure_t& tests) {
+    {
+        html_writer document("runners.html");
+        document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                    "<html>\n"
+                    "  <body bgcolor=\"#FFFFFF\">\n";
+        BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, tests.platforms) {
+            BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                document << "    <table>"
+                            "<tr>"
+                            "<td>"
+                            "<a href=\"" << escape_uri(encode_path(run.runner)) << ".html\">" << escape_xml(run.runner) << "</a>"
+                            "</td>"
+                            "</tr>"
+                            "</table>\n";
+            }
+        }
+        document << "  </body>\n"
+                    "</html>\n";
+    }
+    BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, tests.platforms) {
+        BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+
+            std::cout << "Writing runner document " << encode_path(run.runner) << ".html" << std::endl;
+
+            html_writer document(encode_path(run.runner) + ".html");
+
+            document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\">\n"
+                        "<html>\n"
+                        "  <head>\n"
+                        "<title>" << escape_xml(run.runner) << "</title>\n"
+                        "</head>\n"
+                        "<body>\n"
+                        "<h1>" << escape_xml(run.runner) << "</h1>\n"
+                        "<hr></hr>"
+                     << run.comment // Intentionally not escaped--contains html formatting
+                     << "</body>\n"
+                        "</html>\n";
+        }
+    }
+}
Added: trunk/tools/regression/src/report/runners.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/runners.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,22 @@
+// result_page.cpp
+//
+// Copyright Steven Watanabe 2013
+//
+// Distributed under 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 BOOST_REGRESSION_RUNNERS_HPP
+#define BOOST_REGRESSION_RUNNERS_HPP
+
+#include "xml.hpp"
+
+namespace boost {
+namespace regression {
+    
+void runners(const test_structure_t& tests);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/summary_page.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/summary_page.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,259 @@
+// Copyright MetaCommunications, Inc. 2003-2004.
+// Copyright Steven Watanabe 2013
+//
+// Distributed under 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)
+
+#include <boost/foreach.hpp>
+#include <boost/next_prior.hpp>
+#include "common.hpp"
+#include "summary_page.hpp"
+#include "html_writer.hpp"
+#include "html.hpp"
+#include <iostream>
+
+using namespace boost::regression;
+
+namespace {
+
+// report developer status
+// safe
+void insert_cell_developer(html_writer& document,
+                           const failures_markup_t& explicit_markup,
+                           const std::string& library,
+                           const std::string& toolset,
+                           const test_structure_t::library_t& current_cell,
+                           bool release) {
+
+    std::string class_ = "summary-" + result_cell_class(explicit_markup, library, toolset, current_cell);
+    
+    std::string library_page = encode_path(library);
+
+    document << "<td class=\"" << class_ << "\" title=\"" << escape_xml(library) << "/" << escape_xml(toolset) << "\">\n";
+
+    if(class_ == "summary-unusable") {
+        document << "  "
+                    "<a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"log-link\" target=\"_top\">"
+                    "n/a"
+                    "</a>"
+                    "  ";
+    } else if(class_ == "summary-missing") {
+        document << "    ";
+    } else if(class_ == "summary-fail-unexpected") {
+        document << "<a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"log-link\" target=\"_top\">"
+                    "broken"
+                    "</a>";
+    } else if(class_ == "summary-fail-unexpected-new") {
+        document << "  "
+                    "<a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"log-link\" target=\"_top\">"
+                    "fail"
+                    "</a>"
+                    "  "; 
+    } else {
+        document << "  OK  ";
+    }
+    document << "</td>\n";
+}
+
+// report user status
+// safe
+void insert_cell_user(html_writer& document,
+                      const failures_markup_t& explicit_markup,
+                      const std::string& library,
+                      const std::string& toolset,
+                      const test_structure_t::library_t& current_cell,
+                      bool release) {
+    std::string class_ = "summary-" + result_cell_class(explicit_markup, library, toolset, current_cell);
+    
+    std::string library_page = encode_path(library);
+
+    document << "<td class=\"" << class_ << " user-" << class_ << "\" title=\"" << escape_xml(library) << "/" << escape_xml(toolset) << "\">\n";
+
+    if(class_ == "summary-unusable") {
+        document << " "
+                    "<a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"log-link\" target=\"_top\">"
+                    "unusable"
+                    "</a>"
+                    " ";
+    } else if(class_ == "summary-missing") {
+        document << " no results ";
+    } else if(class_ == "summary-fail-unexpected") {
+        document << " "
+                    "<a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"log-link\" target=\"_top\">"
+                    "regress."
+                    "</a>"
+                    " ";
+    } else if(class_ == "summary-fail-unexpected-new" ||
+              class_ == "summary-fail-expected" ||
+              class_ == "summary-unknown-status" ||
+              class_ == "summary-fail-unexpected-unresearched") {
+        document << " "
+                    "<a href=\"" << escape_uri(library_page) << release_postfix(release) << ".html\" class=\"log-link\" target=\"_top\">"
+                    "details"
+                    "</a>"
+                    " "; 
+    } else {
+        document << " pass ";
+    }
+    document << "</td>\n";
+}
+
+}
+
+// requires: mode = developer | user
+// requires: source is the name of an SVN branch
+void boost::regression::summary_page(const std::string& mode,
+                                     const std::string& source,
+                                     const boost::posix_time::ptime& run_date,
+                                     const std::vector<std::string>& warnings,
+                                     const test_structure_t& tests,
+                                     const failures_markup_t & explicit_markup,
+                                     bool release) {
+
+    std::set<std::string> sorted_libraries;
+    get_libraries(tests, sorted_libraries);
+
+    std::string summary_results("summary" + release_postfix(release) + "_.html");
+
+    std::cout << "Writing document " << "summary" << release_postfix(release) << ".html" << std::endl;
+
+    {
+        html_writer document(mode + "/" + "summary" + release_postfix(release) + ".html");
+
+        document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD html 4.01 Transitional//EN\">\n"
+                    "<html>\n"
+                    "    <head>\n"
+                    "        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+                    "        <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\"/>\n"
+                    "        <title>Boost regression summary: " << source << "</title>\n"
+                    "    </head>\n"
+                    "    <frameset cols=\"190px,*\" frameborder=\"0\" framespacing=\"0\" border=\"0\">\n"
+                    "    <frame name=\"tocframe\" src=\"toc" << release_postfix(release) << ".html\" scrolling=\"auto\"/>\n"
+                    "    <frame name=\"docframe\" src=\"" << summary_results << "\" scrolling=\"auto\"/>\n"
+                    "    </frameset>\n"
+                    "</html>\n";
+    }
+
+    // Summary results
+    std::cout << "Writing document " << summary_results << std::endl;
+
+    {
+        html_writer document(mode + "/" + summary_results);
+
+        document << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\">\n"
+                    "<html>\n"
+                    "<head>\n"
+                    "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
+                    "    <link rel=\"stylesheet\" type=\"text/css\" href=\"../master.css\" title=\"master\"/>\n"
+                    "</head>\n"
+                    "<body>\n";
+
+        insert_page_links(document, "summary", release, alternate_mode(mode));
+
+        document << "<h1 class=\"page-title\">\n"
+                    "    Summary: \n"
+                    "    <a class=\"hover-link\" href=\"summary" << release_postfix(release) << ".html\" target=\"_top\">" << source << "</a>\n"
+                    "</h1>\n";
+
+        insert_report_header(document, run_date, warnings);
+
+        std::size_t num_unusable = 0;
+        std::size_t num_regressions = 0;
+        std::size_t num_new_failures = 0;
+
+        BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, tests.platforms) {
+            BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                BOOST_FOREACH(test_structure_t::toolset_group_t::const_reference toolset, run.toolsets) {
+                    BOOST_FOREACH(test_structure_t::toolset_t::const_reference library, toolset.second) {
+                        bool unusable = is_unusable(explicit_markup, library.first, toolset.first);
+                        BOOST_FOREACH(test_structure_t::library_t::const_reference test_case, library.second) {
+                            BOOST_FOREACH(test_structure_t::test_case_t::const_reference test_log, test_case.second) {
+                                if(unusable) ++num_unusable;
+                                else if(!test_log.result && !test_log.status) {
+                                    if(test_log.is_new) ++num_new_failures;
+                                    else ++num_regressions;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        document << "<div class=\"statistics\">\n"
+                    "Unusable: " << num_unusable << "\n"
+                    " | \n"
+                    "Regressions: " << num_regressions << "\n"
+                    " | \n"
+                    "New failures: " << num_new_failures << "\n"
+                    "</div>\n";
+            
+       // summary table
+
+       document << "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"1%\" class=\"summary-table\" summary=\"Overall summary\">\n";
+
+       document << "<thead>\n";
+       insert_runners_rows(document, "summary", "top", tests, run_date);
+       insert_toolsets_row(document, tests, explicit_markup, "summary", run_date);
+       document << "</thead>\n";
+
+       document << "<tfoot>\n";
+       insert_toolsets_row(document, tests, explicit_markup, "summary", run_date);
+       insert_runners_rows(document, "summary", "bottom", tests, run_date);
+       document << "</tfoot>\n";
+          
+       document << "<tbody>\n";
+
+       BOOST_FOREACH(const std::string& library, sorted_libraries) {
+           std::string library_page = encode_path(library);
+
+           std::string library_header =
+                        "<td class=\"library-name\">\n"
+                        "    <a href=\"" + escape_uri(library_page) + release_postfix(release) + ".html\" class=\"library-link\" target=\"_top\">\n"
+                        "        " + escape_xml(library) + "\n"
+                        "    </a>\n"
+                        "</td>\n";
+
+           std::string line_mod;
+           if(sorted_libraries.size() == 1) line_mod = "-single";
+           else if(library == *sorted_libraries.begin()) line_mod = "-first";
+           else if(library == *boost::prior(sorted_libraries.end())) line_mod = "-last";
+
+           document << "<tr class=\"summary-row" << line_mod << "\">\n";
+           document << library_header;
+
+           test_structure_t::library_t empty_library;
+            BOOST_FOREACH(test_structure_t::platform_group_t::const_reference platform, tests.platforms) {
+                BOOST_FOREACH(test_structure_t::platform_t::const_reference run, platform.second) {
+                    BOOST_FOREACH(test_structure_t::toolset_group_t::const_reference toolset, run.toolsets) {
+                        test_structure_t::toolset_t::const_iterator pos = toolset.second.find(library);
+                        const test_structure_t::library_t * current_cell =
+                            (pos != toolset.second.end())?
+                                &pos->second : &empty_library;
+                        if(mode == "user") {
+                            insert_cell_user(document, explicit_markup, library, toolset.first, *current_cell, release);
+                        } else {
+                            insert_cell_developer(document, explicit_markup, library, toolset.first, *current_cell, release);
+                        }
+                    }
+                }
+            }
+                    
+            document << library_header;
+            document << "</tr>\n";
+       }
+        
+        document << "</tbody>\n";
+        document << "</table>\n";
+
+        document << "<div id=\"legend\">\n"
+                 << (mode == "developer"? summary_developer_legend : summary_user_legend) << "\n"
+                    "</div>\n";
+
+        insert_page_links(document, "summary", release, alternate_mode(mode));
+
+        document << "</body>\n";
+        document << "</html>\n";
+    }
+}
Added: trunk/tools/regression/src/report/summary_page.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/summary_page.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,32 @@
+// result_page.cpp
+//
+// Copyright Steven Watanabe 2013
+//
+// Distributed under 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 BOOST_REGRESSION_SUMMARY_PAGE_HPP
+#define BOOST_REGRESSION_SUMMARY_PAGE_HPP
+
+#include <boost/filesystem/path.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include <string>
+#include <vector>
+#include "xml.hpp"
+
+namespace boost {
+namespace regression {
+
+void summary_page(const std::string& mode,
+                  const std::string& source,
+                  const boost::posix_time::ptime& run_date,
+                  const std::vector<std::string>& warnings,
+                  const test_structure_t& tests,
+                  const failures_markup_t & explicit_markup,
+                  bool release);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/xml.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/xml.cpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,388 @@
+// xml.cpp
+//
+// Copyright (c) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanyiong file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "xml.hpp"
+#include "common.hpp"
+
+#include <boost/date_time/posix_time/time_parsers.hpp>
+#include <boost/functional/hash.hpp>
+#include <fstream>
+#include <boost/format.hpp>
+#include <boost/foreach.hpp>
+
+using namespace boost::regression;
+
+std::size_t boost::regression::hash_value(const test_case_t& test_case) {
+    std::size_t result = 0;
+    boost::hash_combine(result, test_case.test_name);
+    boost::hash_combine(result, test_case.library);
+    boost::hash_combine(result, test_case.toolset_name);
+    return result;
+}
+
+bool boost::regression::operator==(const test_case_t& lhs, const test_case_t& rhs) {
+    return lhs.test_name == rhs.test_name &&
+           lhs.library == rhs.library &&
+           lhs.toolset_name == rhs.toolset_name;
+}
+
+boost::regression::node_ptr boost::regression::lookup_element(node_ptr element, const std::string& name);
+
+boost::regression::attr_ptr boost::regression::lookup_attr(node_ptr element, const std::string& name) {
+    if(element == 0) return 0;
+    return element->first_attribute(name.data(), name.size());
+}
+
+bool boost::regression::lookup_attr(node_ptr element, const std::string& name, std::string& result) {
+    if(element == 0) return false;
+    if(attr_ptr attr = lookup_attr(element, name)) {
+        result = std::string(attr->value(), attr->value_size());
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void require_attr(node_ptr element, const std::string& name, std::string& result) {
+    if(!lookup_attr(element, name, result)) {
+        throw xml_error("Missing attribute " + name + " in element " + std::string(element->name(), element->name_size()));
+    }
+}
+
+bool boost::regression::check_attr(node_ptr element, const std::string& name, const std::string& expected) {
+    if(attr_ptr attr = lookup_attr(element, name)) {
+        return std::string(attr->value(), attr->value_size()) == expected;
+    } else {
+        return false;
+    }
+}
+
+bool boost::regression::check_name(node_ptr element, const std::string& name) {
+    return std::string(element->name(), element->name_size()) == name;
+}
+
+bool boost::regression::check_attr(node_ptr element,
+                const std::string& element1,
+                const std::string& attr,
+                const std::string& expected) {
+    if(element == 0) return false;
+    else if(element1 == "*") {
+        FOR_EACH_ELEMENT(nested, element) {
+            if(check_attr(nested, attr, expected)) {
+                return true;
+            }
+        }
+        return false;
+    } else {
+        return check_attr(lookup_element(element, element1), attr, expected);
+    }
+}
+
+boost::regression::node_ptr boost::regression::lookup_element(node_ptr element, const std::string& name) {
+    if(element == 0) {
+        return 0;
+    } else {
+        return element->first_node(name.data(), name.size());
+    }
+}
+
+int boost::regression::count_element(node_ptr element, const std::string& name) {
+    int result = 0;
+    element = element->first_node(name.data(), name.size());
+    while(element != 0) {
+        ++result;
+        element = element->next_sibling(name.data(), name.size());
+    }
+    return result;
+}
+
+std::string boost::regression::value_of(node_ptr element) {
+    if(element && element->value() != 0) {
+        return std::string(element->value(), element->value_size());
+    } else {
+        return std::string();
+    }
+}
+
+void boost::regression::load_failures_markup(node_ptr root, failures_markup_t& failures_markup) {
+    if(check_name(root, "library")) {
+        std::string library;
+        lookup_attr(root, "name", library);
+        failures_markup.libraries.insert(std::make_pair(library, root));
+    } else if(check_name(root, "mark-toolset")) {
+        if(check_attr(root, "status", "required")) {
+            std::string name;
+            if(lookup_attr(root, "name", name)) {
+                failures_markup.required_toolsets.insert(name);
+            }
+        }
+    } else if(check_name(root, "note")) {
+        std::string refid;
+        if(lookup_attr(root, "id", refid)) {
+            failures_markup.notes.insert(std::make_pair(refid, root));
+        }
+    } else {
+        FOR_EACH_ELEMENT(elem, root) {
+            load_failures_markup(elem, failures_markup);
+        }
+    }
+}
+
+namespace {
+
+void load_test_log(node_ptr root, test_structure_t::test_log_t& test_log) {
+    lookup_attr(root, "library", test_log.library);
+    lookup_attr(root, "test-program", test_log.test_program);
+    test_log.show_run_output = check_attr(root, "show-run-output", "true");
+    lookup_attr(root, "toolset", test_log.toolset);
+    lookup_attr(root, "test-type", test_log.test_type);
+    lookup_attr(root, "test-name", test_log.test_name);
+    lookup_attr(root, "target-directory", test_log.target_directory);
+    // these are set by add_expected_results
+    test_log.result = false; // check_attr(root, "result", "success");
+    test_log.expected_result = false; // check_attr(root, "expected-result", "success");
+    // lookup_attr(root, "expected-reason", test_log.expected_reason);
+    test_log.status = check_attr(root, "status", "expected");
+    test_log.is_new = check_attr(root, "is-new", "yes");
+    lookup_attr(root, "category", test_log.category);
+
+    // process compile/run/etc.
+    FOR_EACH_ELEMENT(elem, root) {
+        std::string name(elem->name(), elem->name_size());
+        if(name != "") {
+            test_structure_t::target_t& target = test_log.targets[name];
+            target.type = name;
+            lookup_attr(elem, "timestamp", target.timestamp);
+            target.result = !check_attr(elem, "result", "fail");
+            target.contents = elem;
+        }
+    }
+}
+
+void collect_toolsets(node_ptr root, test_structure_t::toolset_group_t& out, test_structure_t::toolset_group_t& non_test_case_targets) {
+    if(check_name(root, "test-log")) {
+        std::string toolset;
+        if(lookup_attr(root, "toolset", toolset)) {
+            std::string library, test_name;
+            lookup_attr(root, "library", library);
+            lookup_attr(root, "test-name", test_name);
+
+            test_structure_t::test_log_t log;
+            load_test_log(root, log);
+            if(is_test_log_a_test_case(log))
+                out[toolset][library][test_name].push_back(log);
+            else
+                non_test_case_targets[toolset][library][test_name].push_back(log);
+        }
+    } else {
+        FOR_EACH_ELEMENT(elem, root) {
+            collect_toolsets(elem, out, non_test_case_targets);
+        }
+    }
+}
+
+// FIXME: Make sure that Boost.DateTime handles parsing errors correctly
+boost::posix_time::ptime parse_time(std::string arg) {
+    // fix up some formatting problems
+    if(!arg.empty() && arg[arg.size() - 1] == 'Z') arg.resize(arg.size() - 1);
+    std::replace(arg.begin(), arg.end(), 'T', ' ');
+    return boost::posix_time::time_from_string(arg);
+}
+
+void validate_run(const test_structure_t::run_t& run) {
+    if(run.run_type != "incremental" && run.run_type != "full") {
+        BOOST_THROW_EXCEPTION(xml_error("Expected run-type to be \"incremental\" or \"full\""));
+    }
+    BOOST_FOREACH(char ch, run.revision) {
+        if(!('0' <= ch && ch <= '9')) {
+            BOOST_THROW_EXCEPTION(xml_error("Expected revision to be a numeric constant"));
+        }
+    }
+}
+
+}
+
+void boost::regression::load_test_structure(node_ptr root, test_structure_t& structure, std::vector<test_structure_t::run_t*>& runs) {
+    if(check_name(root, "test-run")) {
+        test_structure_t::run_t run;
+        std::string timestamp;
+        require_attr(root, "runner", run.runner);
+        require_attr(root, "platform", run.platform);
+        require_attr(root, "run-type", run.run_type);
+        require_attr(root, "source", run.source);
+        require_attr(root, "revision", run.revision);
+        require_attr(root, "timestamp", timestamp);
+        // "2010-05-11T18:29:17Z"
+        run.timestamp = parse_time(timestamp);
+        run.comment = value_of(lookup_element(root, "comment"));
+        validate_run(run);
+        collect_toolsets(root, run.toolsets, run.non_test_case_targets);
+        structure.platforms[run.platform].push_back(run);
+        runs.push_back(&structure.platforms[run.platform].back());
+    } else {
+        FOR_EACH_ELEMENT(elem, root) {
+            load_test_structure(elem, structure, runs);
+        }
+    }
+}
+
+namespace {
+
+struct escaped {
+    const char* input;
+    std::size_t size;
+    bool trim;
+};
+
+// okay
+void write_characters(html_writer& document, const char* input, std::size_t size) {
+    for(std::size_t i = 0; i < size; ++i) {
+        if(input[i] == '<') {
+            document << "<";
+        } else if(input[i] == '>') {
+            document << ">";
+        } else if(input[i] == '&') {
+            document << "&";
+        } else {
+            document << input[i];
+        }
+    }
+}
+
+// FIXME: do not break in the middle of a code point
+html_writer& operator<<(html_writer& document, const escaped& text) {
+    std::size_t max_size = 1 << 16;
+    if(text.trim && (text.size > max_size)) {
+        write_characters(document, text.input, max_size);
+        document << str(boost::format("...\n\n[The content has been trimmed by the report system because it exceeds %d bytes]") % max_size);
+    } else {
+        write_characters(document, text.input, text.size);
+    }
+    return document;
+}
+
+escaped make_escaped(const char* input, std::size_t size, bool trim) {
+    escaped result = { input, size, trim };
+    return result;
+}
+
+std::string escape_characters(const char* input, std::size_t size) {
+    std::string result;
+    for(std::size_t i = 0; i < size; ++i) {
+        if(input[i] == '<') {
+            result += "<";
+        } else if(input[i] == '>') {
+            result += ">";
+        } else if(input[i] == '&') {
+            result += "&";
+        } else if(input[i] == '\'') {
+            result += "'";
+        } else if(input[i] == '"') {
+            result += """;
+        } else {
+            result += input[i];
+        }
+    }
+    return result;
+}
+}
+
+std::string boost::regression::escape_xml(const std::string& s) {
+    return escape_characters(s.data(), s.size());
+}
+
+void boost::regression::write_to_stream(html_writer& os, node_ptr node, bool trim) {
+    using namespace boost::property_tree::detail::rapidxml;
+    switch(node->type()) {
+        case node_document:
+            FOR_EACH_ELEMENT(elem, node) {
+                write_to_stream(os, elem);
+            }
+            break;
+        case node_element:
+            os << '<' << escape_characters(node->name(), node->name_size());
+            for(attr_ptr attr = node->first_attribute(); attr != 0; attr = attr->next_attribute()) {
+                os << ' ' << std::string(attr->name(), attr->name_size()) << '=' << '"' << escape_characters(attr->value(), attr->value_size()) << '"';
+            }
+            os << '>';
+            FOR_EACH_ELEMENT(elem, node) {
+                write_to_stream(os, elem);
+            }
+            os << '<' << '/' << escape_characters(node->name(), node->name_size()) << '>';
+            break;
+        case node_data:
+            os << make_escaped(node->value(), node->value_size(), trim);
+            break;
+        default:
+            throw xml_error("Don't know how to handle element type");
+    }
+}
+
+void boost::regression::write_contents(html_writer& os, node_ptr node, bool trim) {
+    FOR_EACH_ELEMENT(elem, node) {
+        write_to_stream(os, elem, trim);
+    }
+}
+
+namespace {
+struct node_storage : document_type {
+    std::vector<char> storage;
+};
+}
+
+boost::shared_ptr<document_type> boost::regression::read_xml_file(const char* filename) {
+    std::ifstream input(filename);
+    if(!input) {
+        throw(std::ios_base::failure(std::string("Could not open file: ") + filename));
+    }
+    boost::shared_ptr<node_storage> result(new node_storage());
+    std::streambuf* buf = input.rdbuf();
+    std::streambuf::int_type ch;
+    while((ch = buf->sbumpc()) != std::char_traits<char>::eof()) {
+        result->storage.push_back(ch);
+    }
+    result->storage.push_back('\0');
+    result->parse<boost::property_tree::detail::rapidxml::parse_default>(&result->storage[0]);
+    return result;
+}
+
+namespace {
+
+void load_expected_results(node_ptr root, test_case_t id, expected_results_t& expected_results) {
+    if(check_name(root, "test-result")) {
+        lookup_attr(root, "test-name", id.test_name);
+        bool result = !check_attr(root, "result", "fail");
+        expected_results.tests.insert(std::make_pair(id, result));
+    } else {
+        if(check_name(root, "toolset")) {
+            std::string name;
+            lookup_attr(root, "name", name);
+            id.toolset_name = name;
+            FOR_EACH_ELEMENT(elem, root) {
+                if(check_name(elem, "toolset-alias")) {
+                    std::string alias_name;
+                    if(lookup_attr(elem, "name", alias_name)) {
+                        expected_results.toolset_aliases.insert(std::make_pair(alias_name, name));
+                    }
+                }
+            }
+        } else if(check_name(root, "library")) {
+            lookup_attr(root, "name", id.library);
+        }
+        FOR_EACH_ELEMENT(elem, root) {
+            load_expected_results(elem, id, expected_results);
+        }
+    }
+}
+
+}
+
+void boost::regression::load_expected_results(node_ptr root, expected_results_t& expected_results) {
+    test_case_t id;
+    ::load_expected_results(root, id, expected_results);
+}
Added: trunk/tools/regression/src/report/xml.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/xml.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,133 @@
+// xml.hpp
+//
+// Copyright (c) 2010 Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanyiong file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef XML_HPP_INCLUDED
+#define XML_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <iosfwd>
+#include <boost/unordered_map.hpp>
+#include <boost/unordered_set.hpp>
+#include <boost/property_tree/detail/rapidxml.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include <boost/variant.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "html_writer.hpp"
+
+namespace boost {
+namespace regression {
+
+class xml_error : public std::exception {
+public:
+    explicit xml_error(const std::string& m) : message(m) {}
+    virtual ~xml_error() throw() {}
+    virtual const char * what() const throw() { return message.c_str(); }
+private:
+    std::string message;
+};
+
+typedef boost::property_tree::detail::rapidxml::xml_node<> node_type;
+typedef boost::property_tree::detail::rapidxml::xml_attribute<> attr_type;
+typedef boost::property_tree::detail::rapidxml::xml_document<> document_type;
+typedef node_type* node_ptr;
+typedef attr_type* attr_ptr;
+typedef document_type* document_ptr;
+
+struct test_case_t {
+    std::string toolset_name;
+    std::string library;
+    std::string test_name;
+};
+
+std::size_t hash_value(const test_case_t& test_case);
+bool operator==(const test_case_t& lhs, const test_case_t& rhs);
+
+struct expected_results_t {
+    typedef boost::unordered_map<test_case_t, bool> tests_t;
+    typedef boost::unordered_map<std::string, std::string> toolset_aliases_t;
+    tests_t tests;
+    toolset_aliases_t toolset_aliases;
+};
+void load_expected_results(node_ptr root, expected_results_t& expected_results);
+
+struct test_structure_t {
+    struct target_t {
+        std::string type;
+        std::string timestamp;
+        bool result;
+        node_ptr contents;
+    };
+    typedef boost::variant<std::string, node_ptr> note_t;
+    struct test_log_t {
+        std::string library;
+        std::string test_program;
+        bool show_run_output;
+        std::string toolset;
+        std::string test_type;
+        std::string test_name;
+        std::string target_directory;
+        bool result;
+        bool expected_result;
+        std::string expected_reason;
+        bool status;
+        bool is_new;
+        std::string category;
+        boost::unordered_map<std::string, target_t> targets;
+        std::vector<note_t> notes;
+    };
+    typedef std::vector<test_log_t> test_case_t;
+    typedef boost::unordered_map<std::string, test_case_t> library_t;
+    typedef boost::unordered_map<std::string, library_t> toolset_t;
+    typedef std::map<std::string, toolset_t> toolset_group_t;
+    struct run_t {
+        std::string runner;
+        std::string platform;
+        std::string run_type;
+        std::string source;
+        std::string revision;
+        std::string comment;
+        boost::posix_time::ptime timestamp;
+        toolset_group_t toolsets;
+        toolset_group_t non_test_case_targets;
+    };
+    typedef std::vector<run_t> platform_t;
+    typedef std::map<std::string, platform_t> platform_group_t;
+    platform_group_t platforms;
+};
+void load_test_structure(node_ptr root, test_structure_t& structure, std::vector<test_structure_t::run_t*>& runs);
+
+struct failures_markup_t {
+    boost::unordered_map<std::string, node_ptr> libraries;
+    boost::unordered_set<std::string> required_toolsets;
+    boost::unordered_map<std::string, node_ptr> notes;
+};
+void load_failures_markup(node_ptr root, failures_markup_t& failures_markup);
+
+#define FOR_EACH_ELEMENT(name, node)\
+    for(::boost::regression::node_ptr name = (node)->first_node(); name != 0; name = name->next_sibling())
+
+attr_ptr lookup_attr(node_ptr element, const std::string& name);
+bool lookup_attr(node_ptr element, const std::string& name, std::string& result);
+bool check_attr(node_ptr element, const std::string& name, const std::string& expected);
+bool check_name(node_ptr element, const std::string& name);
+bool check_attr(node_ptr element, const std::string& element1, const std::string& attr, const std::string& expected);
+node_ptr lookup_element(node_ptr element, const std::string& name);
+int count_element(node_ptr element, const std::string& name);
+std::string value_of(node_ptr element);
+
+std::string escape_xml(const std::string& s);
+void write_to_stream(html_writer& os, node_ptr node, bool trim=false);
+void write_contents(html_writer& document, node_ptr node, bool trim=false);
+boost::shared_ptr<document_type> read_xml_file(const char* filename);
+
+}
+}
+
+#endif
Added: trunk/tools/regression/src/report/zip.hpp
==============================================================================
--- (empty file)
+++ trunk/tools/regression/src/report/zip.hpp	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -0,0 +1,733 @@
+// zip.hpp
+//
+// Copyright (c) 2010, 2013
+// Steven Watanabe
+//
+// Distributed under 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 BOOST_ZIP_ZIP_HPP_INCLUDED
+#define BOOST_ZIP_ZIP_HPP_INCLUDED
+
+#include <cstring>
+#include <ostream>
+#include <string>
+#include <cstddef>
+#include <vector>
+#include <bitset>
+#include <ios>
+
+#include <boost/array.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/crc.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/operations.hpp>
+#include <boost/iostreams/filter/zlib.hpp>
+#include <boost/mpl/integral_c.hpp>
+
+namespace boost {
+namespace zip {
+
+// TODO: Handle endian conversions
+#define BOOST_ZIP_DEFINE_HEADER(name, type, offset)                 \
+    static const int name##_offset = (offset);                      \
+    static type get_##name(const char* header) {                    \
+        type result;                                                \
+        ::std::memcpy(&result, header + (offset), sizeof(type));    \
+        return result;                                              \
+    }                                                               \
+    static void set_##name(char* header, type x) {                  \
+        ::std::memcpy(header + (offset), &x, sizeof(type));         \
+    }
+
+class zip_archive {
+public:
+    zip_archive(std::ostream& file) : output_file(file), current_offset(0), num_files(0) {}
+    ~zip_archive() {
+        close();
+    }
+    
+    class file_handle;
+    friend class file_handle;
+    class file_handle {
+    public:
+        typedef char char_type;
+
+        struct category :
+            ::boost::iostreams::sink_tag,
+            ::boost::iostreams::closable_tag
+        {};
+
+        file_handle(zip_archive& archive,
+                    const std::string& path,
+                    boost::uint16_t creator_version,
+                    boost::uint16_t minimum_required_version,
+                    boost::uint16_t flags,
+                    boost::uint16_t compression_method,
+                    const boost::posix_time::ptime& modification_time) 
+        {
+            self = 0;
+            archive.open_file(path, creator_version, minimum_required_version, flags, compression_method, modification_time, this);
+        }
+        ::std::streamsize write(const char* data, ::std::streamsize size) {
+            assert(self != 0);
+            self->output_file.write(data, size);
+            compressed_size += size;
+            self->current_offset += size;
+            return size;
+        }
+        void write_uncompressed(const char* data, ::std::streamsize size) {
+            assert(self != 0);
+            crc.process_bytes(data, static_cast<std::size_t>(size));
+            uncompressed_size += size;
+        }
+        void close() {
+            central_directory_entry::set_crc32(&self->central_directory[offset], crc.checksum());
+            // These lines cause a warning.  Since the warning is legitimate,
+            // I'm leaving it.
+            central_directory_entry::set_compressed_size(&self->central_directory[offset], compressed_size);
+            central_directory_entry::set_uncompressed_size(&self->central_directory[offset], uncompressed_size);
+
+            boost::array<char, 12> buffer;
+            data_descriptor::set_crc32(&buffer[0], crc.checksum());
+            data_descriptor::set_compressed_size(&buffer[0], compressed_size);
+            data_descriptor::set_uncompressed_size(&buffer[0], uncompressed_size);
+            std::streamsize current_pos = self->output_file.tellp();
+            self->output_file.seekp(pos);
+            self->output_file.write(&buffer[0], 12);
+            self->output_file.seekp(current_pos);
+            self = 0;
+        }
+    private:
+        friend class zip_archive;
+        file_handle(const file_handle&);
+        file_handle& operator=(const file_handle&);
+
+        boost::crc_32_type crc;
+        std::streamsize pos;
+        std::size_t offset;
+        std::streamsize compressed_size;
+        std::streamsize uncompressed_size;
+        zip_archive* self;
+    };
+    
+    void open_file(const std::string& path,
+                   boost::uint16_t creator_version,
+                   boost::uint16_t minimum_required_version,
+                   boost::uint16_t flags,
+                   boost::uint16_t compression_method,
+                   const boost::posix_time::ptime& modification_time,
+                   file_handle* out
+                   )
+    {
+        boost::uint16_t date =
+            modification_time.date().day() +
+            (modification_time.date().month() << 5) +
+            ((modification_time.date().year() - 1980) << 9);
+        boost::uint16_t time =
+            (modification_time.time_of_day().seconds() / 2) +
+            (modification_time.time_of_day().minutes() << 5) +
+            (modification_time.time_of_day().hours() << 11);
+        open_file(path.data(), path.size(), creator_version, minimum_required_version, flags, compression_method, time, date, out);
+    }
+
+    void open_file(const char* path, std::size_t path_size,
+                   boost::uint16_t creator_version,
+                   boost::uint16_t minimum_required_version,
+                   boost::uint16_t flags,
+                   boost::uint16_t compression_method,
+                   boost::uint16_t modification_time,
+                   boost::uint16_t modification_date,
+                   file_handle* handle
+                   )
+    {
+        // The file_handle should not be open
+        assert(handle->self == 0);
+        
+        handle->pos = static_cast<std::streamsize>(output_file.tellp()) + local_file_header::crc32_offset;
+        
+        std::vector<char> header(30);
+        local_file_header::set_signature(&header[0], local_file_header::signature);
+        local_file_header::set_minimum_required_version(&header[0], minimum_required_version);
+        local_file_header::set_flags(&header[0], flags);
+        local_file_header::set_compression_method(&header[0], compression_method);
+
+        local_file_header::set_filename_size(&header[0], path_size);
+        // TODO: handle Zip64
+        header.insert(header.end(), path, path + path_size);
+
+        output_file.write(&header[0], header.size());
+
+        std::size_t offset = central_directory.size();
+        central_directory.resize(offset + 46);
+        central_directory_entry::set_signature(¢ral_directory[offset], central_directory_entry::signature);
+        central_directory_entry::set_creator_version(¢ral_directory[offset], creator_version);
+        central_directory_entry::set_minimum_required_version(¢ral_directory[offset], minimum_required_version);
+        central_directory_entry::set_flags(¢ral_directory[offset], flags);
+        central_directory_entry::set_compression_method(¢ral_directory[offset], compression_method);
+        central_directory_entry::set_modification_time(¢ral_directory[offset], modification_time);
+        central_directory_entry::set_modification_date(¢ral_directory[offset], modification_date);
+        central_directory_entry::set_filename_size(¢ral_directory[offset], path_size);
+        central_directory_entry::set_extra_size(¢ral_directory[offset], 0);
+        central_directory_entry::set_comment_size(¢ral_directory[offset], 0);
+        central_directory_entry::set_file_start_disk(¢ral_directory[offset], 0);
+        central_directory_entry::set_internal_attributes(¢ral_directory[offset], 0);
+        central_directory_entry::set_external_attributes(¢ral_directory[offset], 0);
+        central_directory_entry::set_local_header_offset(¢ral_directory[offset], current_offset);
+        central_directory.insert(central_directory.end(), path, path + path_size);
+        
+        handle->crc.reset();
+        handle->offset = offset;
+        handle->compressed_size = 0;
+        handle->uncompressed_size = 0;
+        handle->self = this;
+
+        current_offset += header.size();
+        ++num_files;
+    }
+
+    void write_file(const std::string& path, const char* contents, std::size_t size) {
+        std::vector<char> header(30);
+        local_file_header::set_signature(&header[0], local_file_header::signature);
+        local_file_header::set_minimum_required_version(&header[0], 10);
+        local_file_header::set_flags(&header[0], 0);
+        local_file_header::set_compression_method(&header[0], compression_method::none);
+        
+        crc_32_type crc;
+        crc.process_bytes(contents, size);
+        local_file_header::set_crc32(&header[0], crc.checksum());
+        local_file_header::set_compressed_size(&header[0], size);
+        local_file_header::set_uncompressed_size(&header[0], size);
+        local_file_header::set_filename_size(&header[0], path.size());
+        // TODO: handle Zip64
+        header.insert(header.end(), path.begin(), path.end());
+
+        output_file.write(&header[0], header.size());
+        output_file.write(contents, size);
+
+        std::size_t offset = central_directory.size();
+        central_directory.resize(offset + 46);
+        central_directory_entry::set_signature(¢ral_directory[offset], central_directory_entry::signature);
+        central_directory_entry::set_creator_version(¢ral_directory[offset], 10);
+        central_directory_entry::set_minimum_required_version(¢ral_directory[offset], 10);
+        central_directory_entry::set_flags(¢ral_directory[offset], 0);
+        central_directory_entry::set_compression_method(¢ral_directory[offset], compression_method::none);
+        // FIXME: find correct date and time
+        central_directory_entry::set_modification_time(¢ral_directory[offset], 0);
+        central_directory_entry::set_modification_date(¢ral_directory[offset], 0);
+        central_directory_entry::set_crc32(¢ral_directory[offset], crc.checksum());
+        central_directory_entry::set_compressed_size(¢ral_directory[offset], size);
+        central_directory_entry::set_uncompressed_size(¢ral_directory[offset], size);
+        central_directory_entry::set_filename_size(¢ral_directory[offset], path.size());
+        central_directory_entry::set_extra_size(¢ral_directory[offset], 0);
+        central_directory_entry::set_comment_size(¢ral_directory[offset], 0);
+        central_directory_entry::set_file_start_disk(¢ral_directory[offset], 0);
+        central_directory_entry::set_internal_attributes(¢ral_directory[offset], 0);
+        central_directory_entry::set_external_attributes(¢ral_directory[offset], 0);
+        central_directory_entry::set_local_header_offset(¢ral_directory[offset], current_offset);
+        central_directory.insert(central_directory.end(), path.begin(), path.end());
+        current_offset = current_offset + header.size() + size;
+
+        ++num_files;
+    }
+    void close() {
+        output_file.write(¢ral_directory[0], central_directory.size());
+        
+        if(num_files >= 65536) {
+            boost::array<char, zip64_end_of_central_directory::size> data;
+            zip64_end_of_central_directory::set_signature(&data[0], zip64_end_of_central_directory::signature);
+            zip64_end_of_central_directory::set_size(&data[0], zip64_end_of_central_directory::size - 12);
+            zip64_end_of_central_directory::set_creator_version(&data[0], 45);
+            zip64_end_of_central_directory::set_minimum_required_version(&data[0], 45);
+            zip64_end_of_central_directory::set_disk_number(&data[0], 0);
+            zip64_end_of_central_directory::set_directory_start_disk(&data[0], 0);
+            zip64_end_of_central_directory::set_entries_on_disk(&data[0], num_files);
+            zip64_end_of_central_directory::set_total_entries(&data[0], num_files);
+            zip64_end_of_central_directory::set_directory_size(&data[0], central_directory.size());
+            zip64_end_of_central_directory::set_directory_offset(&data[0], current_offset);
+            output_file.write(&data[0], data.size());
+
+            boost::array<char, zip64_end_of_central_directory_locator::size> locator;
+            zip64_end_of_central_directory_locator::set_signature(&locator[0], zip64_end_of_central_directory_locator::signature);
+            zip64_end_of_central_directory_locator::set_end_of_directory_disk(&locator[0], 0);
+            zip64_end_of_central_directory_locator::set_end_of_directory_offset(&locator[0], current_offset + central_directory.size());
+            zip64_end_of_central_directory_locator::set_total_disks(&locator[0], 1);
+            output_file.write(&locator[0], locator.size());
+            
+            std::vector<char> end(22);
+            end_of_central_directory::set_signature(&end[0], end_of_central_directory::signature);
+            end_of_central_directory::set_disk_number(&end[0], 0);
+            end_of_central_directory::set_directory_start_disk(&end[0], 0);
+            end_of_central_directory::set_entries_on_disk(&end[0], 0xFFFFu);
+            end_of_central_directory::set_total_entries(&end[0], 0xFFFFu);
+            end_of_central_directory::set_directory_size(&end[0], central_directory.size());
+            end_of_central_directory::set_directory_offset(&end[0], current_offset);
+            end_of_central_directory::set_comment_length(&end[0], 0);
+            output_file.write(&end[0], end.size());
+        } else {
+            std::vector<char> end(22);
+            end_of_central_directory::set_signature(&end[0], end_of_central_directory::signature);
+            end_of_central_directory::set_disk_number(&end[0], 0);
+            end_of_central_directory::set_directory_start_disk(&end[0], 0);
+            end_of_central_directory::set_entries_on_disk(&end[0], num_files);
+            end_of_central_directory::set_total_entries(&end[0], num_files);
+            end_of_central_directory::set_directory_size(&end[0], central_directory.size());
+            end_of_central_directory::set_directory_offset(&end[0], current_offset);
+            end_of_central_directory::set_comment_length(&end[0], 0);
+            output_file.write(&end[0], end.size());
+        }
+    }
+private:
+
+    std::ostream& output_file;
+    std::vector<char> central_directory;
+    std::streamsize current_offset;
+    std::size_t num_files;
+
+    // little endian
+    struct local_file_header {
+        static const boost::uint32_t signature = 0x04034b50u;
+
+        BOOST_ZIP_DEFINE_HEADER(signature,                boost::uint32_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(minimum_required_version, boost::uint16_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(flags,                    boost::uint16_t, 6);
+        BOOST_ZIP_DEFINE_HEADER(compression_method,       boost::uint16_t, 8);
+        BOOST_ZIP_DEFINE_HEADER(modification_time,        boost::uint16_t, 10);
+        BOOST_ZIP_DEFINE_HEADER(modification_date,        boost::uint16_t, 12);
+        BOOST_ZIP_DEFINE_HEADER(crc32,                    boost::uint32_t, 14);
+        BOOST_ZIP_DEFINE_HEADER(compressed_size,          boost::uint32_t, 18);
+        BOOST_ZIP_DEFINE_HEADER(uncompressed_size,        boost::uint32_t, 22);
+        BOOST_ZIP_DEFINE_HEADER(filename_size,            boost::uint16_t, 26);
+        BOOST_ZIP_DEFINE_HEADER(extra_size,               boost::uint16_t, 28);
+
+        static char* filename(void* header) {
+            return static_cast<char*>(header) + 30;
+        }
+        const char* filename(const void* header) {
+            return static_cast<const char*>(header) + 30;
+        }
+    };
+
+    struct data_descriptor {
+        // The signature may or may not be present
+        static const boost::uint32_t signature = 0x08074b50u;
+        BOOST_ZIP_DEFINE_HEADER(crc32,                    boost::uint32_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(compressed_size,          boost::uint32_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(uncompressed_size,        boost::uint32_t, 8);
+        // FIXME: handle skipping the signature automatically
+    };
+
+    // Not implemented Archive decryption header
+    // Not implemented Archive extra data record
+
+    struct central_directory_entry {
+        static const boost::uint32_t signature = 0x02014b50u;
+        BOOST_ZIP_DEFINE_HEADER(signature,                boost::uint32_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(creator_version,          boost::uint16_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(minimum_required_version, boost::uint16_t, 6);
+        BOOST_ZIP_DEFINE_HEADER(flags,                    boost::uint16_t, 8);
+        BOOST_ZIP_DEFINE_HEADER(compression_method,       boost::uint16_t, 10);
+        BOOST_ZIP_DEFINE_HEADER(modification_time,        boost::uint16_t, 12);
+        BOOST_ZIP_DEFINE_HEADER(modification_date,        boost::uint16_t, 14);
+        BOOST_ZIP_DEFINE_HEADER(crc32,                    boost::uint32_t, 16);
+        BOOST_ZIP_DEFINE_HEADER(compressed_size,          boost::uint32_t, 20);
+        BOOST_ZIP_DEFINE_HEADER(uncompressed_size,        boost::uint32_t, 24);
+        BOOST_ZIP_DEFINE_HEADER(filename_size,            boost::uint16_t, 28);
+        BOOST_ZIP_DEFINE_HEADER(extra_size,               boost::uint16_t, 30);
+        BOOST_ZIP_DEFINE_HEADER(comment_size,             boost::uint16_t, 32);
+        BOOST_ZIP_DEFINE_HEADER(file_start_disk,          boost::uint16_t, 34);
+        BOOST_ZIP_DEFINE_HEADER(internal_attributes,      boost::uint16_t, 36);
+        BOOST_ZIP_DEFINE_HEADER(external_attributes,      boost::uint32_t, 38);
+        BOOST_ZIP_DEFINE_HEADER(local_header_offset,      boost::uint32_t, 42);
+
+        // TODO: filename, extra, comment
+    };
+
+    struct digital_signature {
+        static const boost::uint32_t signature = 0x05054b50;
+
+        BOOST_ZIP_DEFINE_HEADER(data_size, boost::uint16_t, 4);
+        // TODO: data
+    };
+
+    struct zip64_end_of_central_directory {
+        static const boost::uint32_t signature = 0x06064b50u;
+        // The value stored into the "size of zip64 end of central
+        // directory record" should be the size of the remaining
+        // record and should not include the leading 12 bytes.
+        BOOST_ZIP_DEFINE_HEADER(signature,                boost::uint32_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(size,                     boost::uint64_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(creator_version,          boost::uint16_t, 12);
+        BOOST_ZIP_DEFINE_HEADER(minimum_required_version, boost::uint16_t, 14);
+        BOOST_ZIP_DEFINE_HEADER(disk_number,              boost::uint32_t, 16);
+        BOOST_ZIP_DEFINE_HEADER(directory_start_disk,     boost::uint32_t, 20);
+        BOOST_ZIP_DEFINE_HEADER(entries_on_disk,          boost::uint64_t, 24);
+        BOOST_ZIP_DEFINE_HEADER(total_entries,            boost::uint64_t, 32);
+        BOOST_ZIP_DEFINE_HEADER(directory_size,           boost::uint64_t, 40);
+        BOOST_ZIP_DEFINE_HEADER(directory_offset,         boost::uint64_t, 48);
+
+        static const size_t size = 56;
+        // TODO: data
+        //           Header ID  -  2 bytes
+        //           Data Size  -  4 bytes
+    };
+
+    // H
+    struct zip64_end_of_central_directory_locator {
+        static const boost::uint32_t signature = 0x07064b50;
+        BOOST_ZIP_DEFINE_HEADER(signature,                boost::uint32_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(end_of_directory_disk,    boost::uint32_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(end_of_directory_offset,  boost::uint64_t, 8);
+        BOOST_ZIP_DEFINE_HEADER(total_disks,              boost::uint32_t, 16);
+
+        static const size_t size = 20;
+    };
+
+    struct end_of_central_directory {
+        static const uint32_t signature = 0x06054b50u;
+        BOOST_ZIP_DEFINE_HEADER(signature,                boost::uint32_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(disk_number,              boost::uint16_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(directory_start_disk,     boost::uint16_t, 6);
+        BOOST_ZIP_DEFINE_HEADER(entries_on_disk,          boost::uint16_t, 8);
+        BOOST_ZIP_DEFINE_HEADER(total_entries,            boost::uint16_t, 10);
+        BOOST_ZIP_DEFINE_HEADER(directory_size,           boost::uint32_t, 12);
+        BOOST_ZIP_DEFINE_HEADER(directory_offset,         boost::uint32_t, 16);
+        BOOST_ZIP_DEFINE_HEADER(comment_length,           boost::uint16_t, 20);
+    };
+    
+public:
+
+    struct version {
+        static const boost::uint16_t system_mask   = 0xFF00u;
+        static const boost::uint16_t ms_dos        =  0u << 8;
+        static const boost::uint16_t amiga         =  1u << 8;
+        static const boost::uint16_t open_vms      =  2u << 8;
+        static const boost::uint16_t unix_         =  3u << 8;
+        static const boost::uint16_t vm_cms        =  4u << 8;
+        static const boost::uint16_t atari_st      =  5u << 8;
+        static const boost::uint16_t os_2_hpfs     =  6u << 8;
+        static const boost::uint16_t macintosh     =  7u << 8;
+        static const boost::uint16_t z_system      =  8u << 8;
+        static const boost::uint16_t cp_m          =  9u << 8;
+        static const boost::uint16_t windows_ntfs  = 10u << 8;
+        static const boost::uint16_t mvs           = 11u << 8;
+        static const boost::uint16_t vse           = 12u << 8;
+        static const boost::uint16_t acorn_risc    = 13u << 8;
+        static const boost::uint16_t vfat          = 14u << 8;
+        static const boost::uint16_t alternate_mvs = 15u << 8;
+        static const boost::uint16_t beos          = 16u << 8;
+        static const boost::uint16_t tandem        = 17u << 8;
+        static const boost::uint16_t os_400        = 18u << 8;
+        static const boost::uint16_t darwin        = 19u << 8;
+
+        // e.g. 62 = ZIP 6.2
+        static const boost::uint16_t zip_version_mask = 0xFFu;
+        static const boost::uint16_t default_                        = 10;
+        static const boost::uint16_t file_is_volume_label            = 11;
+        static const boost::uint16_t file_is_folder                  = 20;
+        static const boost::uint16_t file_is_compressed_with_deflate = 20;
+        static const boost::uint16_t zip64                           = 45;
+        // TODO: ...
+    };
+
+    struct flags {
+        static const boost::uint16_t encrypted                 = 0x1u;
+
+        static const boost::uint16_t imploding_8k_dictionary   = 0x2u;
+        static const boost::uint16_t imploding_3_shannon_faro  = 0x4u;
+        static const boost::uint16_t deflating_options_mask    = 0x6u;
+        static const boost::uint16_t deflating_normal          = 0x0u;
+        static const boost::uint16_t deflating_maximum         = 0x2u;
+        static const boost::uint16_t deflating_fast            = 0x4u;
+        static const boost::uint16_t deflating_super_fast      = 0x6u;
+        static const boost::uint16_t lzma_eos                  = 0x2u;
+
+        static const boost::uint16_t has_data_descriptor       = 0x8u;
+        static const boost::uint16_t enhanced_deflating        = 0x10;
+        static const boost::uint16_t strong_encryption         = 0x20;
+        static const boost::uint16_t utf8                      = 0x800;
+        static const boost::uint16_t mask_local_header_data    = 0x2000;
+    };
+
+    struct compression_method {
+        static const boost::uint16_t none        = 0;
+        static const boost::uint16_t shrink      = 1;
+        static const boost::uint16_t reduce_1    = 2;
+        static const boost::uint16_t reduce_2    = 3;
+        static const boost::uint16_t reduce_3    = 4;
+        static const boost::uint16_t reduce_4    = 5;
+        static const boost::uint16_t implode     = 6;
+        static const boost::uint16_t tokenizing  = 7;
+        static const boost::uint16_t deflate     = 8;
+        static const boost::uint16_t deflate64   = 9;
+        static const boost::uint16_t pkware_dcli = 10;
+        static const boost::uint16_t bzip2       = 12;
+        static const boost::uint16_t lzma        = 14;
+        static const boost::uint16_t ibm_terse   = 18;
+        static const boost::uint16_t lz77        = 19;
+        static const boost::uint16_t wavpack     = 97;
+        static const boost::uint16_t ppmd_i_1    = 98;
+    };
+
+    struct internal_attributes {
+        static const boost::uint16_t ascii = 0x1;
+    };
+
+    struct header_id {
+        static const boost::uint16_t zip64                         = 0x0001;
+        static const boost::uint16_t av_info                       = 0x0007;
+        //static const boost::uint16_t extended_language_encoding    = 0x0008;
+        static const boost::uint16_t os_2                          = 0x0009;
+        static const boost::uint16_t ntfs                          = 0x000a;
+        static const boost::uint16_t open_vms                      = 0x000c;
+        static const boost::uint16_t unix_                         = 0x000d;
+        //static const boost::uint16_t file_stream                   = 0x000e;
+        static const boost::uint16_t patch_descriptor              = 0x000f;
+        static const boost::uint16_t x509_certificate              = 0x0014;
+        static const boost::uint16_t x509_certificate_id_file      = 0x0015;
+        static const boost::uint16_t x509_certificate_id_directory = 0x0016;
+        static const boost::uint16_t strong_encryption_header      = 0x0017;
+        static const boost::uint16_t record_management_controls    = 0x0018;
+        static const boost::uint16_t encyption_recipients          = 0x0019;
+        static const boost::uint16_t ibm_uncompressed              = 0x0065;
+        static const boost::uint16_t ibm_compressed                = 0x0066;
+        static const boost::uint16_t poszip4690                    = 0x4690;
+
+        // TODO: Third party mappings
+    };
+
+private:
+    struct zip64_extended_information {
+        BOOST_ZIP_DEFINE_HEADER(tag,                      boost::uint16_t, 0);
+        BOOST_ZIP_DEFINE_HEADER(size,                     boost::uint16_t, 2);
+        BOOST_ZIP_DEFINE_HEADER(uncompressed_size,        boost::uint64_t, 4);
+        BOOST_ZIP_DEFINE_HEADER(compressed_size,          boost::uint64_t, 12);
+        BOOST_ZIP_DEFINE_HEADER(local_header_offset,      boost::uint64_t, 20);
+        BOOST_ZIP_DEFINE_HEADER(disk_start_number,        boost::uint32_t, 28);
+    };
+};
+
+class shrink_filter : ::boost::noncopyable {
+public:
+    typedef char char_type;
+
+    struct category :
+        ::boost::iostreams::output_filter_tag,
+        ::boost::iostreams::closable_tag
+    {};
+
+    shrink_filter()
+    {
+        memory = new lzw_node[1 << 13];
+
+        // no-throw from here on
+        code_size = 9;
+        for(int i = 0; i < (1 << code_size); ++i) {
+            initialize_node(i);
+        }
+        used_codes.set(256);
+        current_node = &root;
+        buf = 0;
+        pos = 0;
+        for(int i = 0; i < 256; ++i) {
+            root.children[i] = make_node(i);
+        }
+        next_code = 257;
+    }
+    ~shrink_filter() {
+        delete[] memory;
+    }
+    template<class Sink>
+    bool put(Sink& sink, char ch) {
+        write_char(static_cast<unsigned char>(ch));
+        return do_write(sink);
+    }
+    template<class Sink>
+    void close(Sink& sink) {
+        if(current_node != &root) {
+            write_code(get_encoding(current_node));
+            current_node = &root;
+        }
+        do_write(sink);
+        if(pos != 0) {
+            ::boost::iostreams::put(sink, buf & 0xFF);
+            pos = 0;
+        }
+    }
+private:
+    template<class Sink>
+    bool do_write(Sink& sink) {
+        while(pos >= 8) {
+            if(!::boost::iostreams::put(sink, static_cast<char>(buf & 0xFF))) {
+                return false;
+            }
+            buf >>= 8;
+            pos -= 8;
+        }
+        return true;
+    }
+    void write_char(unsigned char ch) {
+        if(current_node->children[ch] != 0) {
+            current_node = current_node->children[ch];
+        } else {
+            int encoding = get_encoding(current_node);
+            write_code(encoding);
+            for(;; ++next_code) {
+                if(next_code == (1 << code_size)) {
+                    if(code_size == 13) {
+                        write_code(256);
+                        write_code(2);
+                        free_leaves();
+                        next_code = 257;
+                    } else {
+                        write_code(256);
+                        write_code(1);
+                        increment_code_size();
+                    }
+                }
+                if(!used_codes.test(next_code)) {
+                    current_node->children[ch] = make_node(next_code);
+                    ++next_code;
+                    break;
+                }
+            }
+            current_node = root.children[ch];
+        }
+    }
+    void write_code(int code) {
+        buf |= static_cast<boost::uint64_t>(code) << pos;
+        pos += code_size;
+    }
+
+    struct lzw_node {
+        lzw_node* children[256];
+    };
+    int get_encoding(lzw_node* node) const {
+        return node - memory;
+    }
+    bool free_leaves(lzw_node* node) {
+        bool result = true;
+        for(int i = 0; i < 256; ++i) {
+            if(node->children[i] != 0) {
+                result = false;
+                if(free_leaves(node->children[i])) {
+                    destroy_node(node->children[i]);
+                    node->children[i] = 0;
+                }
+            }
+        }
+        return result;
+    }
+    void increment_code_size() {
+        for(int i = (1 << code_size); i < (1 << (code_size + 1)); ++i) {
+            initialize_node(i);
+        }
+        ++code_size;
+    }
+    void free_leaves() {
+        for(int i = 0; i < 256; ++i) {
+            free_leaves(root.children[i]);
+        }
+    }
+    void initialize_node(int encoding) {
+        lzw_node* result = memory + encoding;
+        for(int i = 0; i < 256; ++i) {
+            result->children[i] = 0;
+        }
+    }
+    lzw_node* make_node(int encoding = 0) {
+        assert(!used_codes.test(encoding));
+        lzw_node* result = memory + encoding;
+        assert(result >= memory);
+        assert(result < memory + (1 << code_size));
+        used_codes.set(encoding);
+        return result;
+    }
+    void destroy_node(lzw_node* node) {
+        used_codes.reset(get_encoding(node));
+    }
+    lzw_node* memory;
+    lzw_node root;
+    lzw_node* current_node;
+    int code_size;
+    int next_code;
+    ::std::bitset<(1 << 13)> used_codes;
+    ::boost::uint64_t buf;
+    int pos;
+};
+
+class deflate_filter : public ::boost::iostreams::zlib_compressor {
+public:
+    deflate_filter() :
+        boost::iostreams::zlib_compressor(boost::iostreams::zlib_params(
+            boost::iostreams::zlib::default_compression,
+            boost::iostreams::zlib::deflated,
+            boost::iostreams::zlib::default_window_bits,
+            boost::iostreams::zlib::default_mem_level,
+            boost::iostreams::zlib::default_strategy,
+            true /* noheader */,
+            false /* crc */))
+    {}
+};
+
+template<class Filter>
+struct compression_method;
+
+template<>
+struct compression_method< ::boost::zip::shrink_filter> :
+    ::boost::mpl::integral_c<
+        ::boost::uint16_t,
+        ::boost::zip::zip_archive::compression_method::shrink
+    >
+{};
+
+template<>
+struct compression_method< ::boost::zip::deflate_filter> :
+    ::boost::mpl::integral_c<
+        ::boost::uint16_t,
+        ::boost::zip::zip_archive::compression_method::deflate
+    >
+{};
+
+template<class Filter>
+class zip_member_sink {
+public:
+    typedef char char_type;
+
+    struct category :
+        ::boost::iostreams::sink_tag,
+        ::boost::iostreams::closable_tag
+    {};
+
+    zip_member_sink(zip_archive& archive, const std::string& path)
+      : file(archive, path, 10, 10, 0,
+             compression_method<Filter>::value,
+             boost::posix_time::second_clock::local_time()) {}
+    ~zip_member_sink() {
+        close();
+    }
+    ::std::streamsize write(const char* data, ::std::streamsize size) {
+        file.write_uncompressed(data, size);
+        ::boost::iostreams::write(filter, file, data, size);
+        return size;
+    }
+    void close() {
+        ::boost::iostreams::close(filter, file, ::std::ios_base::out);
+        ::boost::iostreams::close(file);
+    }
+private:
+    zip_archive::file_handle file;
+    Filter filter;
+};
+
+typedef zip_member_sink<shrink_filter> shrink_sink;
+typedef zip_member_sink<deflate_filter> deflate_sink;
+
+}
+}
+
+#endif
Modified: trunk/tools/regression/xsl_reports/boost_wide_report.py
==============================================================================
--- trunk/tools/regression/xsl_reports/boost_wide_report.py	(original)
+++ trunk/tools/regression/xsl_reports/boost_wide_report.py	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -470,6 +470,7 @@
         , dont_collect_logs
         , expected_results_file
         , failures_markup_file
+        , report_executable
         ):
 
     incoming_dir = os.path.join( results_dir, 'incoming', tag )
@@ -489,6 +490,29 @@
         ftp_task( ftp_site, site_path, incoming_dir )
 
     unzip_archives_task( incoming_dir, processed_dir, utils.unzip )
+
+    if report_executable:
+        if not os.path.exists( merged_dir ):
+            os.makedirs( merged_dir )
+
+        command_line = report_executable
+        command_line += " --expected " + '"%s"' % expected_results_file 
+        command_line += " --markup " + '"%s"' % failures_markup_file
+        command_line += " --tag " + tag
+        # command_line += " --run-date " + '"%s"' % run_date
+        command_line += " -rl"
+        for r in reports:
+            command_line += ' -r' + r
+        command_line += " --css " + xsl_path( 'html/master.css' )
+
+        for f in glob.glob( os.path.join( processed_dir, '*.xml' ) ):
+            command_line += ' "%s"' % f
+
+        utils.log("Producing the reports...")
+        os.system(command_line)
+
+        return
+
     merge_xmls_task( incoming_dir, processed_dir, merged_dir, expected_results_file, failures_markup_file, tag )
     make_links_task( merged_dir
                      , output_dir
@@ -696,6 +720,7 @@
         , result_file_prefix
         , dont_collect_logs = 0
         , reports = report_types
+        , report_executable = None
         , warnings = []
         , user = None
         , upload = False
@@ -732,6 +757,7 @@
         , dont_collect_logs
         , expected_results_file
         , failures_markup_file
+        , report_executable
         )
 
     if upload:
@@ -759,6 +785,7 @@
         , 'results-prefix='
         , 'dont-collect-logs'
         , 'reports='
+        , 'boost-report='
         , 'user='
         , 'upload'
         , 'help'
@@ -769,6 +796,7 @@
         , '--expected-results': ''
         , '--failures-markup': ''
         , '--reports': string.join( report_types, ',' )
+        , '--boost-report': None
         , '--tag': None
         , '--user': None
         , 'upload': False
@@ -791,6 +819,7 @@
         , options[ '--results-prefix' ]
         , options.has_key( '--dont-collect-logs' )
         , options[ '--reports' ].split( ',' )
+        , options[ '--boost-report' ]
         , options[ '--user' ]
         , options.has_key( '--upload' )
         )
Modified: trunk/tools/regression/xsl_reports/build_results.sh
==============================================================================
--- trunk/tools/regression/xsl_reports/build_results.sh	(original)
+++ trunk/tools/regression/xsl_reports/build_results.sh	2013-03-25 11:47:16 EDT (Mon, 25 Mar 2013)
@@ -92,6 +92,9 @@
     cd ${1}
     root=`pwd`
     boost=${cwd}/boost
+    if [ -x ${cwd}/boost_report ]; then
+      report_opt=--boost-report=${cwd}/boost_report
+    fi
     case ${1} in
         trunk)
         tag=trunk
@@ -114,14 +117,15 @@
         ;;
     esac
     report_info
-    python "${boost}/tools/regression/xsl_reports/boost_wide_report.py" \
+    python "/mnt/hgfs/boost/trunk/tools/regression/xsl_reports/boost_wide_report.py" \
         --locate-root="${root}" \
         --tag=${tag} \
         --expected-results="${boost}/status/expected_results.xml" \
         --failures-markup="${boost}/status/explicit-failures-markup.xml" \
         --comment="comment.html" \
         --user="" \
-        --reports=${reports}
+        --reports=${reports} \
+        ${report_opt}
     cd "${cwd}"
 }
 
@@ -130,11 +134,15 @@
     cwd=`pwd`
     upload_dir=/home/grafik/www.boost.org/testing
     
-    cd ${1}/all
-    rm -f ../../${1}.zip*
-    #~ zip -q -r -9 ../../${1} * -x '*.xml'
-    7za a -tzip -mx=9 ../../${1}.zip * '-x!*.xml'
-    cd "${cwd}"
+    if [ -f ${1}/report.zip ]; then
+        mv ${1}/report.zip ${1}.zip
+    else
+        cd ${1}/all
+        rm -f ../../${1}.zip*
+        #~ zip -q -r -9 ../../${1} * -x '*.xml'
+        7za a -tzip -mx=9 ../../${1}.zip * '-x!*.xml'
+        cd "${cwd}"
+    fi
     mv ${1}.zip ${1}.zip.uploading
     rsync -vuz --rsh=ssh --stats \
       ${1}.zip.uploading grafik_at_[hidden]:/${upload_dir}/incoming/