• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  assert_macro_check implementation  ------------------------------------------------//
2 
3 //  Copyright Eric Niebler 2010.
4 //  Based on the assert_macro_check checker by Marshall Clow
5 //
6 //  Distributed under the Boost Software License, Version 1.0.
7 //  (See accompanying file LICENSE_1_0.txt or copy at
8 //  http://www.boost.org/LICENSE_1_0.txt)
9 
10 #include "assert_macro_check.hpp"
11 #include <functional>
12 #include "boost/regex.hpp"
13 #include "boost/lexical_cast.hpp"
14 #include "boost/filesystem/operations.hpp"
15 
16 namespace fs = boost::filesystem;
17 
18 namespace
19 {
20   boost::regex assert_macro_regex(
21     "("
22     "^\\s*#\\s*undef\\s*" // # undef
23     "\\b(assert)\\b"      // followed by assert macro, whole word
24     ")"
25     "|"                   // or (ignored)
26     "("
27     "//[^\\n]*"           // single line comments (//)
28     "|"
29     "/\\*.*?\\*/"         // multi line comments (/**/)
30     "|"
31     "\"(?:\\\\\\\\|\\\\\"|[^\"])*\"" // string literals
32     ")"
33     "|"                   // or
34     "("
35     "\\b(assert)\\b"  // assert macro, whole word
36     "\\s*\\("         // followed by 0 or more spaces and an opening paren
37     ")"
38     , boost::regex::normal);
39 
40 } // unnamed namespace
41 
42 
43 namespace boost
44 {
45   namespace inspect
46   {
assert_macro_check()47    assert_macro_check::assert_macro_check()
48      : m_files_with_errors(0)
49      , m_from_boost_root(
50          fs::exists(search_root_path() / "boost") &&
51          fs::exists(search_root_path() / "libs"))
52    {
53      register_signature( ".c" );
54      register_signature( ".cpp" );
55      register_signature( ".cxx" );
56      register_signature( ".h" );
57      register_signature( ".hpp" );
58      register_signature( ".hxx" );
59      register_signature( ".ipp" );
60    }
61 
inspect(const string & library_name,const path & full_path,const string & contents)62    void assert_macro_check::inspect(
63       const string & library_name,
64       const path & full_path,   // example: c:/foo/boost/filesystem/path.hpp
65       const string & contents )     // contents of file to be inspected
66     {
67       if (contents.find( "boostinspect:" "naassert_macro" ) != string::npos)
68         return;
69 
70       // Check files iff (a) they are in the boost directory, or (b) they
71       // are in the src directory under libs.
72       if (m_from_boost_root) {
73         path relative( relative_to( full_path, search_root_path() ) );
74         path::const_iterator pbeg = relative.begin(), pend = relative.end();
75         if (pbeg != std::find(pbeg, pend, "boost") &&
76           !(pbeg == std::find(pbeg, pend, "libs") && pend != std::find(pbeg, pend, "src")))
77           return;
78       }
79 
80       long errors = 0;
81       boost::sregex_iterator cur(contents.begin(), contents.end(), assert_macro_regex), end;
82       for( ; cur != end; ++cur )
83       {
84         if(!(*cur)[3].matched)
85         {
86           string::const_iterator it = contents.begin();
87           string::const_iterator match_it = (*cur)[0].first;
88 
89           string::const_iterator line_start = it;
90 
91           string::size_type line_number = 1;
92           for ( ; it != match_it; ++it) {
93               if (string::traits_type::eq(*it, '\n')) {
94                   ++line_number;
95                   line_start = it + 1; // could be end()
96               }
97           }
98 
99           ++errors;
100           error( library_name, full_path, "C-style assert macro on line "
101             + boost::lexical_cast<string>( line_number ) );
102         }
103       }
104       if(errors > 0)
105         ++m_files_with_errors;
106     }
107   } // namespace inspect
108 } // namespace boost
109 
110 
111