Просмотр исходного кода

a) fixed issues related to running outside the boost directory tree.
b) removed processing with process_jam_log as a requirement. The program will still work, but may not include as much information when tests fail.

[SVN r81402]

Robert Ramey 13 лет назад
Родитель
Сommit
270fe97b62
1 измененных файлов с 229 добавлено и 319 удалено
  1. 229 319
      tools/regression/src/library_status.cpp

+ 229 - 319
tools/regression/src/library_status.cpp

@@ -1,5 +1,6 @@
 //  Generate Library Status HTML from jam regression test output  -----------//
 //  Generate Library Status HTML from jam regression test output  -----------//
 
 
+//  Copyright Robert Ramey 2012
 //  Copyright Bryce Lelbach 2011 
 //  Copyright Bryce Lelbach 2011 
 //  Copyright Beman Dawes 2002-2011.
 //  Copyright Beman Dawes 2002-2011.
 
 
@@ -24,15 +25,16 @@ program maintenance.
 
 
 *******************************************************************************/
 *******************************************************************************/
 
 
-#include "boost/filesystem/operations.hpp"
-#include "boost/filesystem/fstream.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/foreach.hpp>
 
 
 namespace fs = boost::filesystem;
 namespace fs = boost::filesystem;
 
 
 #include "detail/tiny_xml.hpp"
 #include "detail/tiny_xml.hpp"
 namespace xml = boost::tiny_xml;
 namespace xml = boost::tiny_xml;
 
 
-#include "boost/iterator/transform_iterator.hpp"
+#include <boost/iterator/transform_iterator.hpp>
 
 
 #include <cstdlib>  // for abort, exit
 #include <cstdlib>  // for abort, exit
 #include <string>
 #include <string>
@@ -40,39 +42,35 @@ namespace xml = boost::tiny_xml;
 #include <set>
 #include <set>
 #include <utility>  // for make_pair on STLPort
 #include <utility>  // for make_pair on STLPort
 #include <map>
 #include <map>
-#include <algorithm>
+#include <algorithm> // max_element, find_if
 #include <iostream>
 #include <iostream>
 #include <fstream>
 #include <fstream>
 #include <ctime>
 #include <ctime>
 #include <stdexcept>
 #include <stdexcept>
 #include <cassert>
 #include <cassert>
-#include <utility>
+#include <utility> // for pair
 
 
 using std::string;
 using std::string;
 
 
 const string pass_msg( "Pass" );
 const string pass_msg( "Pass" );
 const string warn_msg( "<i>Warn</i>" );
 const string warn_msg( "<i>Warn</i>" );
 const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
 const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );
-const string note_msg( "<sup>*</sup>" );
 const string missing_residue_msg( "<i>Missing</i>" );
 const string missing_residue_msg( "<i>Missing</i>" );
 
 
 const std::size_t max_compile_msg_size = 10000;
 const std::size_t max_compile_msg_size = 10000;
 
 
 namespace
 namespace
 {
 {
-    fs::path boost_root;  // boost-root complete path
     fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
     fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path
     bool ignore_pass = false;
     bool ignore_pass = false;
     bool no_warn = false;
     bool no_warn = false;
     bool no_links = false;
     bool no_links = false;
 
 
-    fs::directory_iterator end_itr;
-
     // transform pathname to something html can accept
     // transform pathname to something html can accept
     struct char_xlate {
     struct char_xlate {
         typedef char result_type;
         typedef char result_type;
         result_type operator()(char c) const{
         result_type operator()(char c) const{
-            if(c == '/')
+            if(c == '/' || c == '\\')
                 return '-';
                 return '-';
             return c;
             return c;
         }
         }
@@ -91,12 +89,13 @@ namespace
 
 
     struct col_node {
     struct col_node {
         int rows, cols;
         int rows, cols;
-        bool has_leaf;
+        bool is_leaf;
+        typedef std::pair<const std::string, col_node> subcolumn;
         typedef std::map<std::string, col_node> subcolumns_t;
         typedef std::map<std::string, col_node> subcolumns_t;
         subcolumns_t m_subcolumns;
         subcolumns_t m_subcolumns;
         bool operator<(const col_node &cn) const;
         bool operator<(const col_node &cn) const;
         col_node() :
         col_node() :
-            has_leaf(false)
+            is_leaf(false)
         {}
         {}
         std::pair<int, int> get_spans();
         std::pair<int, int> get_spans();
     };
     };
@@ -104,14 +103,16 @@ namespace
     std::pair<int, int> col_node::get_spans(){
     std::pair<int, int> col_node::get_spans(){
         rows = 1;
         rows = 1;
         cols = 0;
         cols = 0;
-        if(has_leaf){
+        if(is_leaf){
             cols = 1;
             cols = 1;
         }
         }
         if(! m_subcolumns.empty()){
         if(! m_subcolumns.empty()){
-            subcolumns_t::iterator itr;
-            for(itr = m_subcolumns.begin(); itr != m_subcolumns.end(); ++itr){
+            BOOST_FOREACH(
+                subcolumn & s,
+                m_subcolumns
+            ){
                 std::pair<int, int> spans;
                 std::pair<int, int> spans;
-                spans = itr->second.get_spans();
+                spans = s.second.get_spans();
                 rows = (std::max)(rows, spans.first);
                 rows = (std::max)(rows, spans.first);
                 cols += spans.second;
                 cols += spans.second;
             }
             }
@@ -121,86 +122,40 @@ namespace
     }
     }
 
 
     void build_node_tree(const fs::path & dir_root, col_node & node){
     void build_node_tree(const fs::path & dir_root, col_node & node){
-        fs::path xml_file_path( dir_root / "test_log.xml" );
-        if (fs::exists( xml_file_path ) )
-        {
-            node.has_leaf = true;
-        }
-        fs::directory_iterator itr(dir_root);
-        while(itr != end_itr){
-            if(fs::is_directory(*itr)){
+        bool has_directories = false;
+        bool has_files = false;
+        BOOST_FOREACH(
+            fs::directory_entry & d,
+            std::make_pair(
+                fs::directory_iterator(dir_root), 
+                fs::directory_iterator()
+            )
+         ){
+             if(fs::is_directory(d)){
+                has_directories = true;
                 std::pair<col_node::subcolumns_t::iterator, bool> result 
                 std::pair<col_node::subcolumns_t::iterator, bool> result 
                     = node.m_subcolumns.insert(
                     = node.m_subcolumns.insert(
-                        std::make_pair(itr->path().native(), col_node())
+                        std::make_pair(d.path().filename().string(), col_node())
                     );
                     );
-                build_node_tree(*itr, result.first->second);
-            }
-            ++itr;
-        }
+                build_node_tree(d, result.first->second);
+             }
+             else{
+                 has_files = true;
+             }
+        }
+        if(has_directories && has_files)
+            throw std::string("invalid bin directory structure");
+        node.is_leaf = has_files;
     }
     }
 
 
     fs::ofstream report;
     fs::ofstream report;
     fs::ofstream links_file;
     fs::ofstream links_file;
     string links_name;
     string links_name;
 
 
-    fs::path notes_path;
-    string notes_html;
-
-    fs::path notes_map_path;
-    typedef std::multimap< string, string > notes_map; // key is test_name-toolset,
-    // value is note bookmark
-    notes_map notes;
-
     string specific_compiler; // if running on one toolset only
     string specific_compiler; // if running on one toolset only
 
 
     const string empty_string;
     const string empty_string;
 
 
-    //  build notes_bookmarks from notes HTML  -----------------------------------//
-
-    void build_notes_bookmarks()
-    {
-        if ( notes_map_path.empty() ) return;
-        fs::ifstream notes_map_file( notes_map_path );
-        if ( !notes_map_file )
-        {
-            std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl;
-            std::exit( 1 );
-        }
-        string line;
-        while( std::getline( notes_map_file, line ) )
-        {
-            string::size_type pos = 0;
-            if ( (pos = line.find( ',', pos )) == string::npos ) continue;
-            string key(line.substr( 0, pos ) );
-            string bookmark( line.substr( pos+1 ) );
-
-            //      std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n";
-            notes.insert( notes_map::value_type( key, bookmark ) );
-        }
-    }
-
-    //  load_notes_html  ---------------------------------------------------------//
-
-    bool load_notes_html()
-    {
-        if ( notes_path.empty() ) return false;
-        fs::ifstream notes_file( notes_path );
-        if ( !notes_file )
-        {
-            std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl;
-            std::exit( 1 );
-        }
-        string line;
-        bool in_body( false );
-        while( std::getline( notes_file, line ) )
-        {
-            if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false;
-            if ( in_body ) notes_html += line;
-            else if ( line.find( "<body>" ) ) in_body = true;
-        }
-        return true;
-    }
-
     //  extract object library name from target directory string  ----------------//
     //  extract object library name from target directory string  ----------------//
 
 
     string extract_object_library_name( const string & s )
     string extract_object_library_name( const string & s )
@@ -213,30 +168,36 @@ namespace
         return t.substr( pos, t.find( "/", pos ) - pos );
         return t.substr( pos, t.find( "/", pos ) - pos );
     }
     }
 
 
-    //  element_content  ---------------------------------------------------------//
+    //  find_element  ------------------------------------------------------------//
 
 
-    const string & element_content(
-        const xml::element & root, const string & name )
-    {
-        const static string empty_string;
-        xml::element_list::const_iterator itr;
-        for ( itr = root.elements.begin();
-            itr != root.elements.end() && (*itr)->name != name;
-            ++itr ) {}
-            return itr != root.elements.end() ? (*itr)->content : empty_string;
+    xml::element_list::const_iterator find_element(
+        const xml::element & root, const string & name 
+    ){
+        struct element_equal {
+            const string & m_name;
+            element_equal(const string & name) :
+                m_name(name)
+            {}
+            bool operator()(const xml::element_ptr & xep) const {
+                return xep.get()->name == m_name;
+            }
+        };
+        return std::find_if(
+            root.elements.begin(), 
+            root.elements.end(), 
+            element_equal(name)
+        );
     }
     }
 
 
-    //  find_element  ------------------------------------------------------------//
-
-    const xml::element & find_element(
-        const xml::element & root, const string & name )
-    {
-        static const xml::element empty_element;
+    //  element_content  ---------------------------------------------------------//
+    const string & element_content(
+        const xml::element & root, const string & name
+    ){ 
         xml::element_list::const_iterator itr;
         xml::element_list::const_iterator itr;
-        for ( itr = root.elements.begin();
-            itr != root.elements.end() && (*itr)->name != name;
-            ++itr ) {}
-            return itr != root.elements.end() ? *((*itr).get()) : empty_element;
+        itr = find_element(root, name);
+        if(root.elements.end() == itr)
+            return empty_string;
+        return (*itr)->content;
     }
     }
 
 
     //  attribute_value  ----------------------------------------------------------//
     //  attribute_value  ----------------------------------------------------------//
@@ -245,17 +206,26 @@ namespace
         const xml::element & element,
         const xml::element & element,
         const string & attribute_name 
         const string & attribute_name 
     ){
     ){
-        xml::attribute_list::const_iterator atr;
-        for(
-            atr = element.attributes.begin();
-            atr != element.attributes.end();
-            ++atr
-        ){
-            if(atr->name == attribute_name)
-                return atr->value;
+        struct attribute_equal {
+            const string & m_name;
+            attribute_equal(const string & name) :
+                m_name(name)
+            {}
+            bool operator()(const xml::attribute & a) const {
+                return a.name == m_name;
+            }
+        };
+        xml::attribute_list::const_iterator itr;
+        itr = std::find_if(
+            element.attributes.begin(), 
+            element.attributes.end(), 
+            attribute_equal(attribute_name)
+        );
+        if(element.attributes.end() == itr){
+            static const string empty_string;
+            return empty_string;
         }
         }
-        static const string empty_string;
-        return empty_string;
+        return itr->value;
     }
     }
 
 
     //  generate_report  ---------------------------------------------------------//
     //  generate_report  ---------------------------------------------------------//
@@ -303,15 +273,17 @@ namespace
             compile += "...\n   (remainder deleted because of excessive size)\n";
             compile += "...\n   (remainder deleted because of excessive size)\n";
         }
         }
 
 
+        const string target_dir_string = target_dir.string();
+
         links_file << "<h2><a name=\"";
         links_file << "<h2><a name=\"";
         links_file << std::make_pair(
         links_file << std::make_pair(
-            html_from_path(target_dir.string().begin()), 
-            html_from_path(target_dir.string().end())
+            html_from_path(target_dir_string.begin()), 
+            html_from_path(target_dir_string.end())
             )
             )
             << "\">"
             << "\">"
             << std::make_pair(
             << std::make_pair(
-            html_from_path(target_dir.string().begin()), 
-            html_from_path(target_dir.string().end())
+            html_from_path(target_dir_string.begin()), 
+            html_from_path(target_dir_string.end())
             )
             )
             ;
             ;
         links_file << "</a></h2>\n";;
         links_file << "</a></h2>\n";;
@@ -347,14 +319,14 @@ namespace
                 << source_library_name << "-"
                 << source_library_name << "-"
                 << object_library_name << "-" 
                 << object_library_name << "-" 
                 << std::make_pair(
                 << std::make_pair(
-                html_from_path(target_dir.string().begin()), 
-                html_from_path(target_dir.string().end())
+                html_from_path(target_dir_string.begin()), 
+                html_from_path(target_dir_string.end())
                 )
                 )
                 << source_library_name << " - "
                 << source_library_name << " - "
                 << object_library_name << " - " 
                 << object_library_name << " - " 
                 << std::make_pair(
                 << std::make_pair(
-                html_from_path(target_dir.string().begin()), 
-                html_from_path(target_dir.string().end())
+                html_from_path(target_dir_string.begin()), 
+                html_from_path(target_dir_string.end())
                 )
                 )
                 << "</a>";
                 << "</a>";
             if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
             if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() )
@@ -379,14 +351,14 @@ namespace
                     links_file << "<h2><a name=\""
                     links_file << "<h2><a name=\""
                         << object_library_name << "-" 
                         << object_library_name << "-" 
                         << std::make_pair(
                         << std::make_pair(
-                        html_from_path(target_dir.string().begin()), 
-                        html_from_path(target_dir.string().end())
+                        html_from_path(target_dir_string.begin()), 
+                        html_from_path(target_dir_string.end())
                         )
                         )
                         << "\">"
                         << "\">"
                         << object_library_name << " - " 
                         << object_library_name << " - " 
                         << std::make_pair(
                         << std::make_pair(
-                        html_from_path(target_dir.string().begin()), 
-                        html_from_path(target_dir.string().end())
+                        html_from_path(target_dir_string.begin()), 
+                        html_from_path(target_dir_string.end())
                         )
                         )
                         << "</a></h2>\n"
                         << "</a></h2>\n"
                         << "test_log.xml not found\n";
                         << "test_log.xml not found\n";
@@ -396,36 +368,11 @@ namespace
         return result;
         return result;
     }
     }
 
 
-    //  add_notes --------------------------------------------------------------//
-
-    void add_notes( const string & key, bool fail, string & sep, string & target )
-    {
-        notes_map::const_iterator itr = notes.lower_bound( key );
-        if ( itr != notes.end() && itr->first == key )
-        {
-            for ( ; itr != notes.end() && itr->first == key; ++itr )
-            {
-                string note_desc( itr->second[0] == '-'
-                    ? itr->second.substr( 1 ) : itr->second );
-                if ( fail || itr->second[0] == '-' )
-                {
-                    target += sep;
-                    sep = ",";
-                    target += "<a href=\"";
-                    target += "#";
-                    target += note_desc;
-                    target += "\">";
-                    target += note_desc;
-                    target += "</a>";
-                }
-            }
-        }
-    }
-
     //  do_cell  ---------------------------------------------------------------//
     //  do_cell  ---------------------------------------------------------------//
     bool do_cell(
     bool do_cell(
         const fs::path & target_dir,
         const fs::path & target_dir,
         const string & lib_name,
         const string & lib_name,
+        const string & test_name,
         string & target,
         string & target,
         bool profile
         bool profile
     ){
     ){
@@ -435,36 +382,28 @@ namespace
         fs::path xml_file_path( target_dir / "test_log.xml" );
         fs::path xml_file_path( target_dir / "test_log.xml" );
         if ( !fs::exists( xml_file_path ) )
         if ( !fs::exists( xml_file_path ) )
         {
         {
-            // suppress message because there are too many of them.
-            // "missing" is a legitmate result as its not a requirement
-            // that every test be run in every figuration.
-            //std::cerr << "Missing jam_log.xml in target:\n "
-            //    << target_dir.string() << "\n";
-            target += "<td align=\"right\">" + missing_residue_msg + "</td>";
+            fs::path test_path = target_dir / (test_name + ".test");
+            target += "<td align=\"right\">";
+            target += fs::exists( test_path) ? pass_msg : fail_msg;
+            target += "</td>";
             return true;
             return true;
         }
         }
 
 
         int anything_generated = 0;
         int anything_generated = 0;
-        bool note = false;
 
 
-        fs::ifstream file( xml_file_path );
-        if ( !file ) // could not open jam_log.xml
-        {
-            std::cerr << "Can't open jam_log.xml in target:\n "
-                << target_dir.string() << "\n";
-            target += "<td>" + missing_residue_msg + "</td>";
-            return false;
-        }
 
 
         string test_type( "unknown" );
         string test_type( "unknown" );
         bool always_show_run_output( false );
         bool always_show_run_output( false );
 
 
+        fs::ifstream file( xml_file_path );
         xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
         xml::element_ptr dbp = xml::parse( file, xml_file_path.string() );
         const xml::element & db( *dbp );
         const xml::element & db( *dbp );
-        test_type = attribute_value( db, "test-type" );
+
         always_show_run_output
         always_show_run_output
             = attribute_value( db, "show-run-output" ) == "true";
             = attribute_value( db, "show-run-output" ) == "true";
 
 
+        /*
+        test_type = attribute_value( db, "test-type" );
         std::string test_type_base( test_type );
         std::string test_type_base( test_type );
         if ( test_type_base.size() > 5 )
         if ( test_type_base.size() > 5 )
         {
         {
@@ -482,14 +421,15 @@ namespace
                 test_type_base.erase( trailer );
                 test_type_base.erase( trailer );
             }
             }
         }
         }
-        const xml::element & test_type_element( find_element( db, test_type_base ) );
-
-        pass = !test_type_element.name.empty()
-            && attribute_value( test_type_element, "result" ) != "fail";
+        
+        xml::element_list::const_iterator itr;
+        itr = find_element( db, test_type_base );
+        if(db.elements.end() == itr)
+            return pass;
+        */
+        pass = (attribute_value( db, "result" ) != "fail");
 
 
         if (!no_links){
         if (!no_links){
-            if(!test_type_element.name.empty())
-                note = attribute_value( test_type_element, "result" ) == "note";
             anything_generated = 
             anything_generated = 
                 generate_report(
                 generate_report(
                 db, 
                 db, 
@@ -497,7 +437,7 @@ namespace
                 test_type,
                 test_type,
                 target_dir,
                 target_dir,
                 pass,
                 pass,
-                always_show_run_output || note 
+                always_show_run_output
             );
             );
         }
         }
 
 
@@ -508,9 +448,10 @@ namespace
             target += "<a href=\"";
             target += "<a href=\"";
             target += links_name;
             target += links_name;
             target += "#";
             target += "#";
+            const string target_dir_string = target_dir.string();
             std::copy(
             std::copy(
-                html_from_path(target_dir.string().begin()), 
-                html_from_path(target_dir.string().end()),
+                html_from_path(target_dir_string.begin()), 
+                html_from_path(target_dir_string.end()),
                 std::back_inserter(target)
                 std::back_inserter(target)
                 );
                 );
             target += "\">";
             target += "\">";
@@ -518,7 +459,6 @@ namespace
                 ? (anything_generated < 2 ? pass_msg : warn_msg)
                 ? (anything_generated < 2 ? pass_msg : warn_msg)
                 : fail_msg;
                 : fail_msg;
             target += "</a>";
             target += "</a>";
-            if ( pass && note ) target += note_msg;
         }
         }
         else  target += pass ? pass_msg : fail_msg;
         else  target += pass ? pass_msg : fail_msg;
 
 
@@ -529,11 +469,6 @@ namespace
             target += (target_dir / "profile.txt").string();
             target += (target_dir / "profile.txt").string();
             target += "\"><i>Profile</i></a>";
             target += "\"><i>Profile</i></a>";
         }
         }
-        
-        // if notes, generate the superscript HTML
-//        if ( !notes.empty() ) 
-//            target += get_notes( toolset, lib_name, test_name, !pass );
-
         target += "</td>";
         target += "</td>";
         return (anything_generated != 0) || !pass;
         return (anything_generated != 0) || !pass;
     }
     }
@@ -542,32 +477,32 @@ namespace
         const col_node & node,
         const col_node & node,
         fs::path dir_root,
         fs::path dir_root,
         const string & lib_name,
         const string & lib_name,
+        const string & test_name,
         string & target,
         string & target,
         bool profile
         bool profile
     ){
     ){
         bool retval = false;
         bool retval = false;
-        if(node.has_leaf){
+        if(node.is_leaf){
             retval = do_cell(
             retval = do_cell(
                 dir_root,
                 dir_root,
                 lib_name,
                 lib_name,
+                test_name,
                 target,
                 target,
                 profile
                 profile
             );
             );
         }
         }
-
-        col_node::subcolumns_t::const_iterator col_itr;
-        for(
-            col_itr = node.m_subcolumns.begin(); 
-            col_itr != node.m_subcolumns.end();
-            ++col_itr
+        BOOST_FOREACH(
+            const col_node::subcolumn & s,
+            node.m_subcolumns
         ){
         ){
-            fs::path subdir = dir_root / col_itr->first;
+            fs::path subdir = dir_root / s.first;
             retval |= visit_node_tree(
             retval |= visit_node_tree(
-                col_itr->second, 
+                s.second, 
                 subdir,
                 subdir,
                 lib_name,
                 lib_name,
+                test_name,
                 target,
                 target,
-                col_itr->first == "profile"
+                s.first == "profile"
             );
             );
         }
         }
         return retval;
         return retval;
@@ -588,20 +523,17 @@ namespace
         target += "<td>";
         target += "<td>";
         //target += "<a href=\"" + url_prefix_dir_view + "/libs/" + lib_name + "\">";
         //target += "<a href=\"" + url_prefix_dir_view + "/libs/" + lib_name + "\">";
         target += test_name;
         target += test_name;
-        target += "</a>";
+        //target += "</a>";
         target += "</td>";
         target += "</td>";
 
 
-//        target += "<td>" + test_type + "</td>";
-
         bool no_warn_save = no_warn;
         bool no_warn_save = no_warn;
 
 
-//        if ( test_type.find( "fail" ) != string::npos ) no_warn = true;
-
         // emit cells on this row
         // emit cells on this row
         bool anything_to_report = visit_node_tree(
         bool anything_to_report = visit_node_tree(
             test_node, 
             test_node, 
             test_dir,
             test_dir,
             lib_name,
             lib_name,
+            test_name,
             target,
             target,
             false
             false
         );
         );
@@ -625,25 +557,26 @@ namespace
         // rows are held in a vector so they can be sorted, if desired.
         // rows are held in a vector so they can be sorted, if desired.
         std::vector<string> results;
         std::vector<string> results;
 
 
-        for ( fs::directory_iterator itr( test_lib_dir ); itr != end_itr; ++itr )
-        {
-            if(! fs::is_directory(*itr))
+        BOOST_FOREACH(
+            fs::directory_entry & d,
+            std::make_pair(
+                fs::directory_iterator(test_lib_dir), 
+                fs::directory_iterator()
+            )
+         ){
+            if(! fs::is_directory(d))
                 continue;
                 continue;
-            
-            string test_name = itr->path().native();
+
             // if the file name contains ".test"
             // if the file name contains ".test"
-            string::size_type s = test_name.find( ".test" );
-            if(string::npos != s)
-                // strip it off
-                test_name.resize(s);
-            else
-                // if it doesn't - skip this directory
+            if(d.path().extension() != ".test")
                 continue;
                 continue;
 
 
+            string test_name = d.path().stem().string();
+
             results.push_back( std::string() ); 
             results.push_back( std::string() ); 
             do_row(
             do_row(
                 root_node, //*test_node_itr++,
                 root_node, //*test_node_itr++,
-                *itr, // test dir
+                d, // test dir
                 lib_name,
                 lib_name,
                 test_name,
                 test_name,
                 results[results.size()-1] 
                 results[results.size()-1] 
@@ -652,21 +585,18 @@ namespace
 
 
         std::sort( results.begin(), results.end() );
         std::sort( results.begin(), results.end() );
 
 
-        for ( 
-            std::vector<string>::iterator v(results.begin());
-            v != results.end(); 
-            ++v 
-        ){ 
-            report << *v << "\n"; 
-        }
+        BOOST_FOREACH(string &s, results)
+            report << s << "\n";
     }
     }
 
 
     //  column header-----------------------------------------------------------//
     //  column header-----------------------------------------------------------//
     int header_depth(const col_node & root){
     int header_depth(const col_node & root){
-        col_node::subcolumns_t::const_iterator itr;
         int max_depth = 1;
         int max_depth = 1;
-        for(itr = root.m_subcolumns.begin(); itr != root.m_subcolumns.end(); ++itr){
-            max_depth = (std::max)(max_depth, itr->second.rows);
+        BOOST_FOREACH(
+            const col_node::subcolumn &s,
+            root.m_subcolumns
+        ){
+            max_depth = (std::max)(max_depth, s.second.rows);
         }
         }
         return max_depth;
         return max_depth;
     }
     }
@@ -692,23 +622,30 @@ namespace
     ){
     ){
         if(current_row < display_row){
         if(current_row < display_row){
             if(! node.m_subcolumns.empty()){
             if(! node.m_subcolumns.empty()){
-                col_node::subcolumns_t::const_iterator itr;
-                for(itr = node.m_subcolumns.begin(); itr != node.m_subcolumns.end(); ++itr){
-                    emit_column_headers(itr->second, display_row, current_row + 1, row_count);
+                BOOST_FOREACH(
+                    const col_node::subcolumn &s,
+                    node.m_subcolumns
+                ){
+                    emit_column_headers(
+                        s.second, 
+                        display_row, 
+                        current_row + 1, 
+                        row_count
+                    );
                 }
                 }
             }
             }
             return;
             return;
         }
         }
-        if(node.has_leaf && ! node.m_subcolumns.empty()){
+        /*
+        if(node.is_leaf && ! node.m_subcolumns.empty()){
             header_cell(row_count - current_row, 1, std::string(""));
             header_cell(row_count - current_row, 1, std::string(""));
         }
         }
-
-        col_node::subcolumns_t::const_iterator itr;
-        for(itr = node.m_subcolumns.begin(); itr != node.m_subcolumns.end(); ++itr){
-            if(1 == itr->second.rows)
-                header_cell(row_count - current_row, itr->second.cols, itr->first);
+        */
+        BOOST_FOREACH(col_node::subcolumn s, node.m_subcolumns){
+            if(1 == s.second.rows)
+                header_cell(row_count - current_row, s.second.cols, s.first);
             else
             else
-                header_cell(1, itr->second.cols, itr->first);
+                header_cell(1, s.second.cols, s.first);
         }
         }
     }
     }
 
 
@@ -716,9 +653,8 @@ namespace
         // walk up from the path were we started until we find
         // walk up from the path were we started until we find
         // bin or bin.v2
         // bin or bin.v2
 
 
-        fs::path::const_iterator it = initial_path.end(), end = initial_path.end();
         fs::path test_lib_dir = initial_path;
         fs::path test_lib_dir = initial_path;
-        for(;;){
+        do{
             if(fs::is_directory( test_lib_dir / "bin.v2")){
             if(fs::is_directory( test_lib_dir / "bin.v2")){
                 test_lib_dir /= "bin.v2";
                 test_lib_dir /= "bin.v2";
                 break;
                 break;
@@ -726,44 +662,47 @@ namespace
             if(fs::is_directory( test_lib_dir / "bin")){
             if(fs::is_directory( test_lib_dir / "bin")){
                 // v1 includes the word boost
                 // v1 includes the word boost
                 test_lib_dir /= "bin";
                 test_lib_dir /= "bin";
-                test_lib_dir /= "boost";
+                if(fs::is_directory( test_lib_dir / "boost")){
+                    test_lib_dir /= "boost";
+                }
                 break;
                 break;
             }
             }
-            if(test_lib_dir.empty())
-                throw std::string("binary path not found");
-            if(*it != "libs")
-                --it;
-            test_lib_dir.remove_filename();
-        }
+        }while(! test_lib_dir.empty());
 
 
-        if(it == end)
-            throw std::string("must be run from within a library directory");
+        if(test_lib_dir.empty())
+            throw std::string("binary path not found");
 
 
-
-        for(;it != end; ++it){ 
-            test_lib_dir /= *it;    // append "libs"
-        }
         return test_lib_dir;
         return test_lib_dir;
     }
     }
 
 
-    // note : uncomment the #if/#endif and what this compile !!!
     string find_lib_name(fs::path lib_test_dir){
     string find_lib_name(fs::path lib_test_dir){
-        unsigned int count;
+        // search the path backwards for the magic name "libs"
         fs::path::iterator e_itr = lib_test_dir.end();
         fs::path::iterator e_itr = lib_test_dir.end();
-        for(count =  0;; ++count){
+        while(lib_test_dir.begin() != e_itr){
             if(*--e_itr == "libs")
             if(*--e_itr == "libs")
                 break;
                 break;
-            if(lib_test_dir.empty())
-                throw std::string("must be run from within a library directory");
         }
         }
-        string library_name;
-        for(;;){
-            library_name.append((*++e_itr).native());
-            if(1 == --count)
-                break;
-            library_name.append("/");
+
+        // if its found
+        if(lib_test_dir.begin() != e_itr){
+            // use the whole path since the "libs"
+            ++e_itr;
         }
         }
-        return library_name;
+        // otherwise, just use the last two components
+        else{
+            e_itr = lib_test_dir.end();
+            if(e_itr != lib_test_dir.begin()){
+                if(--e_itr != lib_test_dir.begin()){
+                    --e_itr;
+                }
+            }
+        }
+
+        fs::path library_name;
+        while(lib_test_dir.end() != e_itr){
+            library_name /= *e_itr++;
+        }
+        return library_name.string();
     }
     }
 
 
     fs::path find_boost_root(fs::path initial_path){
     fs::path find_boost_root(fs::path initial_path){
@@ -781,19 +720,25 @@ namespace
     }
     }
 
 
     //  do_table  ----------------------------------------------------------------//
     //  do_table  ----------------------------------------------------------------//
-    void do_table(fs::path const& initial_path, const string & lib_name)
+    void do_table(const fs::path & lib_test_dir, const string & lib_name)
     {
     {
         col_node root_node;
         col_node root_node;
 
 
-        fs::path lib_test_dir = find_lib_test_dir(initial_path);
-
-        for ( fs::directory_iterator itr(lib_test_dir); itr != end_itr; ++itr )
-        {
-            if(! fs::is_directory(*itr))
+        BOOST_FOREACH(
+            fs::directory_entry & d,
+            std::make_pair(
+                fs::directory_iterator(lib_test_dir), 
+                fs::directory_iterator()
+            )
+         ){
+            if(! fs::is_directory(d))
                 continue;
                 continue;
-            build_node_tree(*itr, root_node);
+            fs::path p = d.path();
+            if(p.extension() != ".test")
+                continue;
+            build_node_tree(d, root_node);
         }
         }
-
+        
         // visit directory nodes and record nodetree
         // visit directory nodes and record nodetree
         report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
         report << "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n";
 
 
@@ -829,21 +774,12 @@ int cpp_main( int argc, char * argv[] ) // note name!
 {
 {
     fs::path initial_path = fs::initial_path();
     fs::path initial_path = fs::initial_path();
 
 
-    fs::path comment_path;
     while ( argc > 1 && *argv[1] == '-' )
     while ( argc > 1 && *argv[1] == '-' )
     {
     {
         if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
         if ( argc > 2 && std::strcmp( argv[1], "--compiler" ) == 0 )
         { specific_compiler = argv[2]; --argc; ++argv; }
         { specific_compiler = argv[2]; --argc; ++argv; }
         else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
         else if ( argc > 2 && std::strcmp( argv[1], "--locate-root" ) == 0 )
         { locate_root = fs::path( argv[2] ); --argc; ++argv; }
         { locate_root = fs::path( argv[2] ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--boost-root" ) == 0 )
-        { boost_root = fs::path( argv[2] ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--comment" ) == 0 )
-        { comment_path = fs::path( argv[2] ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--notes" ) == 0 )
-        { notes_path = fs::path( argv[2] ); --argc; ++argv; }
-        else if ( argc > 2 && std::strcmp( argv[1], "--notes-map" ) == 0 )
-        { notes_map_path = fs::path( argv[2] ); --argc; ++argv; }
         else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true;
         else if ( std::strcmp( argv[1], "--ignore-pass" ) == 0 ) ignore_pass = true;
         else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
         else if ( std::strcmp( argv[1], "--no-warn" ) == 0 ) no_warn = true;
         else if ( std::strcmp( argv[1], "--v2" ) == 0 )
         else if ( std::strcmp( argv[1], "--v2" ) == 0 )
@@ -864,27 +800,19 @@ int cpp_main( int argc, char * argv[] ) // note name!
             "  options: --compiler name     Run for named compiler only\n"
             "  options: --compiler name     Run for named compiler only\n"
             "           --ignore-pass       Do not report tests which pass all compilers\n"
             "           --ignore-pass       Do not report tests which pass all compilers\n"
             "           --no-warn           Warnings not reported if test passes\n"
             "           --no-warn           Warnings not reported if test passes\n"
-            "           --boost-root path default derived from current path.\n"
             "           --locate-root path  Path to ALL_LOCATE_TARGET for bjam;\n"
             "           --locate-root path  Path to ALL_LOCATE_TARGET for bjam;\n"
             "                               default boost-root.\n"
             "                               default boost-root.\n"
-            "           --comment path      Path to file containing HTML\n"
-            "                               to be copied into status-file.\n"
-            "           --notes path        Path to file containing HTML\n"
-            "                               to be copied into status-file.\n"
-            "           --notes-map path    Path to file of toolset/test,n lines, where\n"
-            "                               n is number of note bookmark in --notes file.\n"
-            "Example: compiler_status --compiler gcc /boost-root cs.html cs-links.html\n"
-            "Note: Only the leaf of the links-file path and --notes file string are\n"
+            "Example: library_status --compiler gcc /boost-root cs.html cs-links.html\n"
+            "Note: Only the leaf of the links-file path is\n"
             "used in status-file HTML links. Thus for browsing, status-file,\n"
             "used in status-file HTML links. Thus for browsing, status-file,\n"
-            "links-file, and --notes file must all be in the same directory.\n"
+            "links-file must be in the same directory.\n"
             ;
             ;
         return 1;
         return 1;
     }
     }
 
 
-    if(boost_root.empty())
-        boost_root = find_boost_root(initial_path);
-    if ( locate_root.empty() ) 
-        locate_root = boost_root;
+    if(locate_root.empty())
+        if(! fs::exists("bin") && ! fs::exists("bin.v2"))
+            locate_root = find_boost_root(initial_path);
 
 
     report.open( fs::path( argv[1] ) );
     report.open( fs::path( argv[1] ) );
     if ( !report )
     if ( !report )
@@ -896,7 +824,7 @@ int cpp_main( int argc, char * argv[] ) // note name!
     if ( argc == 3 )
     if ( argc == 3 )
     {
     {
         fs::path links_path( argv[2] );
         fs::path links_path( argv[2] );
-        links_name = links_path.native();
+        links_name = links_path.filename().string();
         links_file.open( links_path );
         links_file.open( links_path );
         if ( !links_file )
         if ( !links_file )
         {
         {
@@ -906,8 +834,6 @@ int cpp_main( int argc, char * argv[] ) // note name!
     }
     }
     else no_links = true;
     else no_links = true;
 
 
-    build_notes_bookmarks();
-
     const string library_name = find_lib_name(initial_path);
     const string library_name = find_lib_name(initial_path);
 
 
     char run_date[128];
     char run_date[128];
@@ -923,31 +849,12 @@ int cpp_main( int argc, char * argv[] ) // note name!
         << "</head>\n"
         << "</head>\n"
         << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
         << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
         << "<table border=\"0\">\n"
         << "<table border=\"0\">\n"
-        << "<tr>\n"
-        << "<td><img border=\"0\" " 
-        << "src=\""
-        << boost_root / "boost.png"
-        << "\" width=\"277\" "
-        << "height=\"86\"></td>\n"
-        << "<td>\n"
         << "<h1>Library Status: " + library_name + "</h1>\n"
         << "<h1>Library Status: " + library_name + "</h1>\n"
         << "<b>Run Date:</b> "
         << "<b>Run Date:</b> "
         << run_date
         << run_date
-        << "\n"
+        << "\n<br>"
         ;
         ;
 
 
-    if ( !comment_path.empty() )
-    {
-        fs::ifstream comment_file( comment_path );
-        if ( !comment_file )
-        {
-            std::cerr << "Could not open \"--comment\" input file: " << comment_path.string() << std::endl;
-            return 1;
-        }
-        char c;
-        while ( comment_file.get( c ) ) { report.put( c ); }
-    }
-
     report << "</td>\n</table>\n<br>\n";
     report << "</td>\n</table>\n<br>\n";
 
 
     if ( !no_links )
     if ( !no_links )
@@ -959,22 +866,25 @@ int cpp_main( int argc, char * argv[] ) // note name!
             << "</head>\n"
             << "</head>\n"
             << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
             << "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
             << "<table border=\"0\">\n"
             << "<table border=\"0\">\n"
-            << "<tr>\n"
-            << "<td><img border=\"0\" src=\""
-            << boost_root / "boost.png"
-            << "\" width=\"277\" "
-            << "height=\"86\"></td>\n"
-            << "<td>\n"
             << "<h1>Library Status: " + library_name + "</h1>\n"
             << "<h1>Library Status: " + library_name + "</h1>\n"
             << "<b>Run Date:</b> "
             << "<b>Run Date:</b> "
             << run_date
             << run_date
-            << "\n</td>\n</table>\n<br>\n"
+            << "\n<br></table>\n<br>\n"
             ;
             ;
     }
     }
 
 
-    do_table(initial_path, library_name);
+    // detect whether in a a directory which looks like
+    // bin/<library name>/test
+    // or just
+    // bin
+    fs::path library_test_directory = find_lib_test_dir(locate_root);
+    // if libs exists, drop down a couple of levels
+    if(fs::is_directory( library_test_directory / "libs")){
+        library_test_directory /= "libs";
+        library_test_directory /= library_name;
+    }
 
 
-    if ( load_notes_html() ) report << notes_html << "\n";
+    do_table(library_test_directory, library_name);
 
 
     report << "</body>\n"
     report << "</body>\n"
         "</html>\n"
         "</html>\n"

粤ICP备19079148号