Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r63462 - in branches/release/tools/inspect: . build build/msvc
From: daniel_james_at_[hidden]
Date: 2010-06-30 19:33:34


Author: danieljames
Date: 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
New Revision: 63462
URL: http://svn.boost.org/trac/boost/changeset/63462

Log:
Merge inspect from trunk.
Added:
   branches/release/tools/inspect/apple_macro_check.cpp
      - copied, changed from r57825, /trunk/tools/inspect/apple_macro_check.cpp
   branches/release/tools/inspect/apple_macro_check.hpp
      - copied, changed from r57825, /trunk/tools/inspect/apple_macro_check.hpp
   branches/release/tools/inspect/link_check_test.html
      - copied unchanged from r59102, /trunk/tools/inspect/link_check_test.html
Properties modified:
   branches/release/tools/inspect/ (props changed)
Text files modified:
   branches/release/tools/inspect/apple_macro_check.cpp | 25 ++++-
   branches/release/tools/inspect/apple_macro_check.hpp | 2
   branches/release/tools/inspect/ascii_check.cpp | 3
   branches/release/tools/inspect/build/Jamfile.v2 | 2
   branches/release/tools/inspect/build/msvc/boost_inspect.vcproj | 28 +----
   branches/release/tools/inspect/build/msvc/readme.txt | 2
   branches/release/tools/inspect/inspect.cpp | 37 +++++++-
   branches/release/tools/inspect/inspector.hpp | 3
   branches/release/tools/inspect/link_check.cpp | 177 ++++++++++++++++++++++++++++++++-------
   branches/release/tools/inspect/link_check.hpp | 13 ++
   branches/release/tools/inspect/unnamed_namespace_check.cpp | 3
   11 files changed, 222 insertions(+), 73 deletions(-)

Copied: branches/release/tools/inspect/apple_macro_check.cpp (from r57825, /trunk/tools/inspect/apple_macro_check.cpp)
==============================================================================
--- /trunk/tools/inspect/apple_macro_check.cpp (original)
+++ branches/release/tools/inspect/apple_macro_check.cpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -11,13 +11,16 @@
 #include <functional>
 #include "boost/regex.hpp"
 #include "boost/lexical_cast.hpp"
+#include "boost/filesystem/operations.hpp"
+
+namespace fs = boost::filesystem;
 
 namespace
 {
   boost::regex apple_macro_regex(
     "("
     "^\\s*#\\s*undef\\s*" // # undef
- "\\b(min|max)\\b" // followed by min or max, whole word
+ "\\b(check|verify|require|check_error)\\b" // followed by apple macro name, whole word
     ")"
     "|" // or (ignored)
     "("
@@ -29,7 +32,7 @@
     ")"
     "|" // or
     "("
- "\\b(check|verify|require|check_error)\\b" // min or max, whole word
+ "\\b(check|verify|require|check_error)\\b" // apple macro name, whole word
     "\\s*\\(" // followed by 0 or more spaces and an opening paren
     ")"
     , boost::regex::normal);
@@ -59,8 +62,15 @@
     {
       if (contents.find( "boostinspect:" "naapple_macros" ) != string::npos) return;
 
+ // Only check files in the boost directory, as we can avoid including the
+ // apple test headers elsewhere.
+ path relative( relative_to( full_path, fs::initial_path() ), fs::no_check );
+ if ( relative.empty() || *relative.begin() != "boost") return;
+
       boost::sregex_iterator cur(contents.begin(), contents.end(), apple_macro_regex), end;
 
+ long errors = 0;
+
       for( ; cur != end; ++cur /*, ++m_files_with_errors*/ )
       {
 
@@ -79,12 +89,15 @@
               }
           }
 
- ++m_files_with_errors;
- error( library_name, full_path, string(name())
- + " violation of Boost apple-macro guidelines on line "
- + boost::lexical_cast<string>( line_number ) );
+ ++errors;
+ error( library_name, full_path,
+ "Apple macro clash: " + std::string((*cur)[0].first, (*cur)[0].second-1),
+ line_number );
         }
       }
+ if(errors > 0) {
+ ++m_files_with_errors;
+ }
     }
   } // namespace inspect
 } // namespace boost

Copied: branches/release/tools/inspect/apple_macro_check.hpp (from r57825, /trunk/tools/inspect/apple_macro_check.hpp)
==============================================================================
--- /trunk/tools/inspect/apple_macro_check.hpp (original)
+++ branches/release/tools/inspect/apple_macro_check.hpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -31,7 +31,7 @@
         const std::string & contents );
 
       virtual ~apple_macro_check()
- { std::cout << " " << m_files_with_errors << " files with apple macros" << line_break(); }
+ { std::cout << " " << m_files_with_errors << " files with Apple macros" << line_break(); }
     };
   }
 }

Modified: branches/release/tools/inspect/ascii_check.cpp
==============================================================================
--- branches/release/tools/inspect/ascii_check.cpp (original)
+++ branches/release/tools/inspect/ascii_check.cpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -91,8 +91,9 @@
       if ( bad_char != contents.end ())
       {
         ++m_files_with_errors;
+ int ln = std::count( contents.begin(), bad_char, '\n' ) + 1;
         string the_line = find_line ( contents, bad_char );
- error( library_name, full_path, string ( name()) + " non-ASCII: " + the_line );
+ error( library_name, full_path, "Non-ASCII: " + the_line, ln );
       }
     }
   } // namespace inspect

Modified: branches/release/tools/inspect/build/Jamfile.v2
==============================================================================
--- branches/release/tools/inspect/build/Jamfile.v2 (original)
+++ branches/release/tools/inspect/build/Jamfile.v2 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -15,7 +15,7 @@
 exe inspect
     :
     inspect.cpp license_check.cpp link_check.cpp path_name_check.cpp tab_check.cpp crlf_check.cpp end_check.cpp unnamed_namespace_check.cpp ascii_check.cpp
- copyright_check.cpp minmax_check.cpp
+ copyright_check.cpp minmax_check.cpp apple_macro_check.cpp
     /boost//filesystem/<link>static
     /boost//regex/<link>static
     :

Modified: branches/release/tools/inspect/build/msvc/boost_inspect.vcproj
==============================================================================
--- branches/release/tools/inspect/build/msvc/boost_inspect.vcproj (original)
+++ branches/release/tools/inspect/build/msvc/boost_inspect.vcproj 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -2,7 +2,7 @@
 <VisualStudioProject
         ProjectType="Visual C++"
         Version="9.00"
- Name="boost_inspect"
+ Name="inspect"
         ProjectGUID="{0EC8AC1C-6D1F-47FC-A06A-9CC3F924BD82}"
         RootNamespace="boost_inspect"
         Keyword="Win32Proj"
@@ -42,7 +42,7 @@
                                 Name="VCCLCompilerTool"
                                 Optimization="0"
                                 AdditionalIncludeDirectories="..\..\..\.."
- PreprocessorDefinitions="BOOST_SYSTEM_NO_LIB;BOOST_FILESYSTEM_NO_LIB;WIN32;_DEBUG;_CONSOLE"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
                                 MinimalRebuild="true"
                                 ExceptionHandling="2"
                                 BasicRuntimeChecks="3"
@@ -118,7 +118,7 @@
                                 Optimization="2"
                                 EnableIntrinsicFunctions="true"
                                 AdditionalIncludeDirectories="..\..\..\.."
- PreprocessorDefinitions="BOOST_SYSTEM_NO_LIB;BOOST_FILESYSTEM_NO_LIB;WIN32;NDEBUG;_CONSOLE"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
                                 ExceptionHandling="2"
                                 RuntimeLibrary="2"
                                 EnableFunctionLevelLinking="true"
@@ -177,6 +177,10 @@
                         UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
                         <File
+ RelativePath="..\..\apple_macro_check.cpp"
+ >
+ </File>
+ <File
                                 RelativePath="..\..\ascii_check.cpp"
>
                         </File>
@@ -189,7 +193,7 @@
>
                         </File>
                         <File
- RelativePath="..\..\..\..\libs\system\src\error_code.cpp"
+ RelativePath="..\..\end_check.cpp"
>
                         </File>
                         <File
@@ -209,22 +213,10 @@
>
                         </File>
                         <File
- RelativePath="..\..\..\..\libs\filesystem\src\operations.cpp"
- >
- </File>
- <File
- RelativePath="..\..\..\..\libs\filesystem\src\path.cpp"
- >
- </File>
- <File
                                 RelativePath="..\..\path_name_check.cpp"
>
                         </File>
                         <File
- RelativePath="..\..\..\..\libs\filesystem\src\portability.cpp"
- >
- </File>
- <File
                                 RelativePath="..\..\tab_check.cpp"
>
                         </File>
@@ -232,10 +224,6 @@
                                 RelativePath="..\..\unnamed_namespace_check.cpp"
>
                         </File>
- <File
- RelativePath="..\..\..\..\libs\filesystem\src\utf8_codecvt_facet.cpp"
- >
- </File>
                 </Filter>
                 <Filter
                         Name="Header Files"

Modified: branches/release/tools/inspect/build/msvc/readme.txt
==============================================================================
--- branches/release/tools/inspect/build/msvc/readme.txt (original)
+++ branches/release/tools/inspect/build/msvc/readme.txt 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -1,3 +1,3 @@
 The provided Microsoft VC++ solution assumes the following has been run in the root directory"
 
- bjam --toolset=msvc-9.0express --build-type=complete --with-regex stage
\ No newline at end of file
+ bjam --toolset=msvc-9.0express --build-type=complete --with-filesystem,regex stage
\ No newline at end of file

Modified: branches/release/tools/inspect/inspect.cpp
==============================================================================
--- branches/release/tools/inspect/inspect.cpp (original)
+++ branches/release/tools/inspect/inspect.cpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -22,6 +22,7 @@
 #include <cstring>
 
 #include "boost/shared_ptr.hpp"
+#include "boost/lexical_cast.hpp"
 #include "boost/filesystem/operations.hpp"
 #include "boost/filesystem/fstream.hpp"
 
@@ -38,6 +39,7 @@
 #include "path_name_check.hpp"
 #include "tab_check.hpp"
 #include "ascii_check.hpp"
+#include "apple_macro_check.hpp"
 #include "minmax_check.hpp"
 #include "unnamed_namespace_check.hpp"
 
@@ -75,6 +77,7 @@
     string library;
     string rel_path;
     string msg;
+ int line_number;
 
     bool operator<( const error_msg & rhs ) const
     {
@@ -82,6 +85,8 @@
       if ( library > rhs.library ) return false;
       if ( rel_path < rhs.rel_path ) return true;
       if ( rel_path > rhs.rel_path ) return false;
+ if ( line_number < rhs.line_number ) return true;
+ if ( line_number > rhs.line_number ) return false;
       return msg < rhs.msg;
     }
   };
@@ -399,11 +404,11 @@
       }
       std::cout << "\n";
     }
- else
+ else // html
     {
       // display error messages with group indication
       error_msg current;
- string sep;
+ bool first_sep = true;
       bool first = true;
       for ( error_msg_vector::iterator itr ( msgs.begin() );
         itr != msgs.end(); ++itr )
@@ -419,14 +424,26 @@
         {
           std::cout << "\n";
           std::cout << itr->rel_path;
- sep = ": ";
+ first_sep = true;
         }
         if ( current.library != itr->library
           || current.rel_path != itr->rel_path
           || current.msg != itr->msg )
         {
- std::cout << sep << itr->msg;
- sep = ", ";
+ std::string sep;
+ if (first_sep)
+ if (itr->line_number) sep = ":<br>&nbsp;&nbsp;&nbsp; ";
+ else sep = ": ";
+ else
+ if (itr->line_number) sep = "<br>&nbsp;&nbsp;&nbsp; ";
+ else sep = ", ";
+
+ // print the message
+ if (itr->line_number)
+ std::cout << sep << "(line " << itr->line_number << ") " << itr->msg;
+ else std::cout << sep << itr->msg;
+
+ first_sep = false;
         }
         current.library = itr->library;
         current.rel_path = itr->rel_path;
@@ -529,6 +546,7 @@
          " -path_name\n"
          " -tab\n"
          " -ascii\n"
+ " -apple_macro\n"
          " -minmax\n"
          " -unnamed\n"
          " default is all checks on; otherwise options specify desired checks"
@@ -579,13 +597,14 @@
 // error -------------------------------------------------------------------//
 
     void inspector::error( const string & library_name,
- const path & full_path, const string & msg )
+ const path & full_path, const string & msg, int line_number )
     {
       ++error_count;
       error_msg err_msg;
       err_msg.library = library_name;
       err_msg.rel_path = relative_to( full_path, fs::initial_path() );
       err_msg.msg = msg;
+ err_msg.line_number = line_number;
       msgs.push_back( err_msg );
 
 // std::cout << library_name << ": "
@@ -699,6 +718,7 @@
   bool path_name_ck = true;
   bool tab_ck = true;
   bool ascii_ck = true;
+ bool apple_ok = true;
   bool minmax_ck = true;
   bool unnamed_ck = true;
   bool cvs = false;
@@ -731,6 +751,7 @@
     path_name_ck = false;
     tab_ck = false;
     ascii_ck = false;
+ apple_ok = false;
     minmax_ck = false;
     unnamed_ck = false;
   }
@@ -754,6 +775,8 @@
       tab_ck = true;
     else if ( std::strcmp( argv[1], "-ascii" ) == 0 )
       ascii_ck = true;
+ else if ( std::strcmp( argv[1], "-apple_macro" ) == 0 )
+ apple_ok = true;
     else if ( std::strcmp( argv[1], "-minmax" ) == 0 )
         minmax_ck = true;
     else if ( std::strcmp( argv[1], "-unnamed" ) == 0 )
@@ -797,6 +820,8 @@
       inspectors.push_back( inspector_element( new boost::inspect::tab_check ) );
   if ( ascii_ck )
       inspectors.push_back( inspector_element( new boost::inspect::ascii_check ) );
+ if ( apple_ok )
+ inspectors.push_back( inspector_element( new boost::inspect::apple_macro_check ) );
   if ( minmax_ck )
       inspectors.push_back( inspector_element( new boost::inspect::minmax_check ) );
   if ( unnamed_ck )

Modified: branches/release/tools/inspect/inspector.hpp
==============================================================================
--- branches/release/tools/inspect/inspector.hpp (original)
+++ branches/release/tools/inspect/inspector.hpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -64,7 +64,8 @@
       void error(
         const string & library_name,
         const path & full_path,
- const string & msg );
+ const string & msg,
+ int line_number =0 ); // 0 if not available or not applicable
 
     private:
       string_set m_signatures;

Modified: branches/release/tools/inspect/link_check.cpp
==============================================================================
--- branches/release/tools/inspect/link_check.cpp (original)
+++ branches/release/tools/inspect/link_check.cpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -11,17 +11,26 @@
 #include "boost/filesystem/operations.hpp"
 #include <boost/algorithm/string/case_conv.hpp>
 #include <cstdlib>
+#include <set>
+
+// #include <iostream>
 
 namespace fs = boost::filesystem;
 
 namespace
 {
+ boost::regex html_bookmark_regex(
+ "<([^\\s<>]*)\\s*[^<>]*\\s+(NAME|ID)\\s*=\\s*(['\"])(.*?)\\3"
+ "|<!--.*?-->",
+ boost::regbase::normal | boost::regbase::icase);
   boost::regex html_url_regex(
     "<([^\\s<>]*)\\s*[^<>]*\\s+(?:HREF|SRC)" // HREF or SRC
- "\\s*=\\s*(['\"])(.*?)\\2",
+ "\\s*=\\s*(['\"])\\s*(.*?)\\s*\\2"
+ "|<!--.*?-->",
     boost::regbase::normal | boost::regbase::icase);
   boost::regex css_url_regex(
- "(\\@import\\s*[\"']|url\\s*\\(\\s*[\"']?)([^\"')]*)",
+ "(\\@import\\s*[\"']|url\\s*\\(\\s*[\"']?)([^\"')]*)"
+ "|/\\*.*?\\*/",
     boost::regbase::normal | boost::regbase::icase);
 
   // Regular expression for parsing URLS from:
@@ -30,6 +39,10 @@
     "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$",
     boost::regbase::normal);
 
+ typedef std::set<std::string> bookmark_set;
+ bookmark_set bookmarks;
+ bookmark_set bookmarks_lowercase; // duplicate check needs case insensitive
+
   // Decode html escapsed ampersands, returns an empty string if there's an error.
   std::string decode_ampersands(std::string const& url_path) {
     std::string::size_type pos = 0, next;
@@ -95,7 +108,7 @@
 
    link_check::link_check()
      : m_broken_errors(0), m_unlinked_errors(0), m_invalid_errors(0),
- m_bookmark_errors(0)
+ m_bookmark_errors(0), m_duplicate_bookmark_errors(0)
    {
        // HTML signatures are already registered by the base class,
        // 'hypertext_inspector'
@@ -126,6 +139,65 @@
       bool no_link_errors =
           (contents.find( "boostinspect:" "nolink" ) != string::npos);
 
+ // build bookmarks databases
+ bookmarks.clear();
+ bookmarks_lowercase.clear();
+ string::const_iterator a_start( contents.begin() );
+ string::const_iterator a_end( contents.end() );
+ boost::match_results< string::const_iterator > a_what;
+ boost::match_flag_type a_flags = boost::match_default;
+
+ if(!is_css(full_path))
+ {
+ string previous_id;
+
+ while( boost::regex_search( a_start, a_end, a_what, html_bookmark_regex, a_flags) )
+ {
+ // a_what[0] contains the whole string iterators.
+ // a_what[1] contains the tag iterators.
+ // a_what[2] contains the attribute name.
+ // a_what[4] contains the bookmark iterators.
+
+ if (a_what[4].matched)
+ {
+ string tag( a_what[1].first, a_what[1].second );
+ boost::algorithm::to_lower(tag);
+ string attribute( a_what[2].first, a_what[2].second );
+ boost::algorithm::to_lower(attribute);
+ string bookmark( a_what[4].first, a_what[4].second );
+
+ bool name_following_id = ( attribute == "name" && previous_id == bookmark );
+ if ( tag != "meta" && attribute == "id" ) previous_id = bookmark;
+ else previous_id.clear();
+
+ if ( tag != "meta" && !name_following_id )
+ {
+ bookmarks.insert( bookmark );
+// std::cout << "******************* " << bookmark << '\n';
+
+ // w3.org recommends case-insensitive checking for duplicate bookmarks
+ // since some browsers do a case-insensitive match.
+ string bookmark_lowercase( bookmark );
+ boost::algorithm::to_lower(bookmark_lowercase);
+
+ std::pair<bookmark_set::iterator, bool> result
+ = bookmarks_lowercase.insert( bookmark_lowercase );
+ if (!result.second)
+ {
+ ++m_duplicate_bookmark_errors;
+ int ln = std::count( contents.begin(), a_what[3].first, '\n' ) + 1;
+ error( library_name, full_path, "Duplicate bookmark: " + bookmark, ln );
+ }
+ }
+ }
+
+ a_start = a_what[0].second; // update search position
+ a_flags |= boost::match_prev_avail; // update flags
+ a_flags |= boost::match_not_bob;
+ }
+ }
+
+ // process urls
       string::const_iterator start( contents.begin() );
       string::const_iterator end( contents.end() );
       boost::match_results< string::const_iterator > what;
@@ -138,14 +210,17 @@
           // what[0] contains the whole string iterators.
           // what[1] contains the element type iterators.
           // what[3] contains the URL iterators.
+
+ if(what[3].matched)
+ {
+ string type( what[1].first, what[1].second );
+ boost::algorithm::to_lower(type);
 
- string type( what[1].first, what[1].second );
- boost::algorithm::to_lower(type);
-
- // TODO: Complain if 'link' tags use external stylesheets.
- do_url( string( what[3].first, what[3].second ),
- library_name, full_path, no_link_errors,
- type == "a" || type == "link" );
+ // TODO: Complain if 'link' tags use external stylesheets.
+ do_url( string( what[3].first, what[3].second ),
+ library_name, full_path, no_link_errors,
+ type == "a" || type == "link", contents.begin(), what[3].first );
+ }
 
           start = what[0].second; // update search position
           flags |= boost::match_prev_avail; // update flags
@@ -157,8 +232,13 @@
       {
         // what[0] contains the whole string iterators.
         // what[2] contains the URL iterators.
- do_url( string( what[2].first, what[2].second ),
- library_name, full_path, no_link_errors, false );
+
+ if(what[2].matched)
+ {
+ do_url( string( what[2].first, what[2].second ),
+ library_name, full_path, no_link_errors, false,
+ contents.begin(), what[3].first );
+ }
 
         start = what[0].second; // update search position
         flags |= boost::match_prev_avail; // update flags
@@ -169,12 +249,14 @@
 // do_url ------------------------------------------------------------------//
 
     void link_check::do_url( const string & url, const string & library_name,
- const path & source_path, bool no_link_errors, bool allow_external_content )
+ const path & source_path, bool no_link_errors, bool allow_external_content,
+ std::string::const_iterator contents_begin, std::string::const_iterator url_start )
         // precondition: source_path.is_complete()
     {
       if(!no_link_errors && url.empty()) {
         ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " empty URL." );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Empty URL.", ln );
         return;
       }
 
@@ -183,7 +265,9 @@
       if(decoded_url.empty()) {
         if(!no_link_errors) {
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL (invalid ampersand encodings): " + url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (invalid ampersand encodings): " + url, ln );
         }
         return;
       }
@@ -192,7 +276,8 @@
       if(!boost::regex_match(decoded_url, m, url_decompose_regex)) {
         if(!no_link_errors) {
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Invalid URL: " + decoded_url, ln );
         }
         return;
       }
@@ -212,7 +297,8 @@
       if(!allow_external_content && (authority_matched || scheme_matched)) {
         if(!no_link_errors) {
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " external content: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "External content: " + decoded_url, ln );
         }
       }
 
@@ -225,7 +311,8 @@
           if(!authority_matched) {
             if(!no_link_errors) {
               ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " no hostname: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "No hostname: " + decoded_url, ln );
             }
           }
 
@@ -234,19 +321,24 @@
         else if(scheme == "file") {
           if(!no_link_errors) {
             ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL (hardwired file): " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (hardwired file): " + decoded_url, ln );
           }
         }
         else if(scheme == "mailto" || scheme == "ftp" || scheme == "news" || scheme == "javascript") {
           if ( !no_link_errors && is_css(source_path) ) {
             ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid protocol for css: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid protocol for css: " + decoded_url, ln );
           }
         }
         else {
           if(!no_link_errors) {
             ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " unknown protocol: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Unknown protocol: '" + scheme + "' in url: " + decoded_url, ln );
           }
         }
 
@@ -257,7 +349,9 @@
       if(authority_matched) {
         if(!no_link_errors) {
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL (hostname without protocol): " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (hostname without protocol): " + decoded_url, ln );
         }
       }
 
@@ -266,14 +360,26 @@
         if ( is_css(source_path) ) {
             if ( !no_link_errors ) {
               ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " fragment link in CSS: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Fragment link in CSS: " + decoded_url, ln );
             }
         }
         else {
           if ( !no_link_errors && fragment.find( '#' ) != string::npos )
           {
             ++m_bookmark_errors;
- error( library_name, source_path, string(name()) + " invalid bookmark: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Invalid bookmark: " + decoded_url, ln );
+ }
+ else if ( !no_link_errors && url_path.empty() && !fragment.empty()
+ // w3.org recommends case-sensitive broken bookmark checking
+ // since some browsers do a case-sensitive match.
+ && bookmarks.find(decode_percents(fragment)) == bookmarks.end() )
+ {
+ ++m_broken_errors;
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Unknown bookmark: " + decoded_url, ln );
           }
         }
 
@@ -285,23 +391,29 @@
       if ( !no_link_errors && decoded_url.find_first_of( " <>\"{}|\\^[]'" ) != string::npos )
       {
         ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid character in URL: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid character in URL: " + decoded_url, ln );
       }
 
       // Check that we actually have a path.
       if(url_path.empty()) {
         if(!no_link_errors) {
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL (empty path in relative url): " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (empty path in relative url): " + decoded_url, ln );
         }
       }
 
- // Decode percent and ampersand encoded characters.
+ // Decode percent encoded characters.
       string decoded_path = decode_percents(url_path);
       if(decoded_path.empty()) {
         if(!no_link_errors) {
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL (invalid character encodings): " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path,
+ "Invalid URL (invalid character encodings): " + decoded_url, ln );
         }
         return;
       }
@@ -316,8 +428,10 @@
       catch ( const fs::filesystem_error & )
       {
         if(!no_link_errors) {
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
           ++m_invalid_errors;
- error( library_name, source_path, string(name()) + " invalid URL (error resolving path): " + decoded_url );
+ error( library_name, source_path,
+ "Invalid URL (error resolving path): " + decoded_url, ln );
         }
         return;
       }
@@ -339,7 +453,8 @@
       if ( !no_link_errors && (itr->second & m_present) == 0 )
       {
         ++m_broken_errors;
- error( library_name, source_path, string(name()) + " broken link: " + decoded_url );
+ int ln = std::count( contents_begin, url_start, '\n' ) + 1;
+ error( library_name, source_path, "Broken link: " + decoded_url, ln );
       }
     }
 
@@ -362,7 +477,7 @@
        {
          ++m_unlinked_errors;
          path full_path( fs::initial_path() / path(itr->first, fs::no_check) );
- error( impute_library( full_path ), full_path, string(name()) + " unlinked file" );
+ error( impute_library( full_path ), full_path, "Unlinked file" );
        }
      }
    }

Modified: branches/release/tools/inspect/link_check.hpp
==============================================================================
--- branches/release/tools/inspect/link_check.hpp (original)
+++ branches/release/tools/inspect/link_check.hpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -27,18 +27,22 @@
       long m_unlinked_errors;
       long m_invalid_errors;
       long m_bookmark_errors;
+ long m_duplicate_bookmark_errors;
 
       typedef std::map< string, int > m_path_map;
       m_path_map m_paths; // first() is relative initial_path()
 
       void do_url( const string & url, const string & library_name,
         const path & full_source_path, bool no_link_errors,
- bool allow_external_links );
+ bool allow_external_links,
+ std::string::const_iterator contents_begin, std::string::const_iterator url_start);
     public:
 
       link_check();
       virtual const char * name() const { return "*LINK*"; }
- virtual const char * desc() const { return "invalid bookmarks, invalid urls, broken links, unlinked files"; }
+ virtual const char * desc() const
+ { return "invalid bookmarks, duplicate bookmarks,"
+ " invalid urls, broken links, unlinked files"; }
 
       virtual void inspect(
         const std::string & library_name,
@@ -53,7 +57,10 @@
 
       virtual ~link_check()
         {
- std::cout << " " << m_bookmark_errors << " bookmarks with invalid characters" << line_break();
+ std::cout << " " << m_bookmark_errors
+ << " bookmarks with invalid characters" << line_break();
+ std::cout << " " << m_duplicate_bookmark_errors
+ << " duplicate bookmarks" << line_break();
           std::cout << " " << m_invalid_errors << " invalid urls" << line_break();
           std::cout << " " << m_broken_errors << " broken links" << line_break();
           std::cout << " " << m_unlinked_errors << " unlinked files" << line_break();

Modified: branches/release/tools/inspect/unnamed_namespace_check.cpp
==============================================================================
--- branches/release/tools/inspect/unnamed_namespace_check.cpp (original)
+++ branches/release/tools/inspect/unnamed_namespace_check.cpp 2010-06-30 19:33:33 EDT (Wed, 30 Jun 2010)
@@ -51,8 +51,7 @@
         const string::size_type
          ln = std::count( contents.begin(), (*cur)[0].first, '\n' ) + 1;
 
- error( library_name, full_path, string(name()) + " unnamed namespace at line "
- + lexical_cast<string>(ln) );
+ error( library_name, full_path, "Unnamed namespace", ln );
       }
 
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk