[29] | 1 | // minmax_check implementation --------------------------------------------// |
---|
| 2 | |
---|
| 3 | // Copyright Beman Dawes 2002. |
---|
| 4 | // Copyright Gennaro Prota 2006. |
---|
| 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 | |
---|
| 11 | #include <algorithm> |
---|
| 12 | |
---|
| 13 | #include "minmax_check.hpp" |
---|
| 14 | #include "boost/regex.hpp" |
---|
| 15 | #include "boost/lexical_cast.hpp" |
---|
| 16 | |
---|
| 17 | namespace |
---|
| 18 | { |
---|
| 19 | boost::regex minmax_regex( |
---|
| 20 | "(" |
---|
| 21 | "^\\s*#\\s*undef\\s*" // # undef |
---|
| 22 | "\\b(min|max)\\b" // followed by min or max, whole word |
---|
| 23 | ")" |
---|
| 24 | "|" // or |
---|
| 25 | "(" |
---|
| 26 | "\\b(min|max)\\b" // min or max, whole word |
---|
| 27 | "\\s*\\(" // followed by 0 or more spaces and an opening paren |
---|
| 28 | ")" |
---|
| 29 | , boost::regex::normal); |
---|
| 30 | |
---|
| 31 | } // unnamed namespace |
---|
| 32 | |
---|
| 33 | namespace boost |
---|
| 34 | { |
---|
| 35 | namespace inspect |
---|
| 36 | { |
---|
| 37 | |
---|
| 38 | // minmax_check constructor -------------------------------------------// |
---|
| 39 | |
---|
| 40 | minmax_check::minmax_check() |
---|
| 41 | : m_errors(0) |
---|
| 42 | { |
---|
| 43 | // C/C++ source code... |
---|
| 44 | register_signature( ".c" ); |
---|
| 45 | register_signature( ".cpp" ); |
---|
| 46 | register_signature( ".cxx" ); |
---|
| 47 | register_signature( ".h" ); |
---|
| 48 | register_signature( ".hpp" ); |
---|
| 49 | register_signature( ".hxx" ); |
---|
| 50 | register_signature( ".inc" ); |
---|
| 51 | register_signature( ".ipp" ); |
---|
| 52 | } |
---|
| 53 | |
---|
| 54 | // inspect ( C++ source files ) ---------------------------------------// |
---|
| 55 | |
---|
| 56 | void minmax_check::inspect( |
---|
| 57 | const string & library_name, |
---|
| 58 | const path & full_path, // example: c:/foo/boost/filesystem/path.hpp |
---|
| 59 | const string & contents) // contents of file to be inspected |
---|
| 60 | { |
---|
| 61 | if (contents.find( "boostinspect:" "nominmax" ) != string::npos) return; |
---|
| 62 | |
---|
| 63 | boost::sregex_iterator cur(contents.begin(), contents.end(), minmax_regex), end; |
---|
| 64 | |
---|
| 65 | for( ; cur != end; ++cur /*, ++m_errors*/ ) |
---|
| 66 | { |
---|
| 67 | // ~ experimental: try to filter out apparent |
---|
| 68 | // ~ min/max guideline violations in one-line comments |
---|
| 69 | // |
---|
| 70 | // This is just a quick hack to avoid impacting the |
---|
| 71 | // overall application design. To be on the safe side, |
---|
| 72 | // we only aim at one-line comments; the comment must be |
---|
| 73 | // the only non-blank content of the line, and no quote |
---|
| 74 | // character or "*/" shall appear within it. Otherwise we |
---|
| 75 | // give up filtering, at the cost of possible false positives. |
---|
| 76 | // |
---|
| 77 | const string one_line_comment_line ( "^\\s*//" ); |
---|
| 78 | |
---|
| 79 | string::const_iterator it = contents.begin(); |
---|
| 80 | string::const_iterator match_it = (*cur)[0].first; |
---|
| 81 | |
---|
| 82 | string::const_iterator line_start = it; |
---|
| 83 | |
---|
| 84 | string::size_type line_number = 1; |
---|
| 85 | for ( ; it != match_it; ++it) { |
---|
| 86 | if (string::traits_type::eq(*it, '\n')) { |
---|
| 87 | ++line_number; |
---|
| 88 | line_start = it + 1; // could be end() |
---|
| 89 | } |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | string::const_iterator past_line_content = |
---|
| 93 | std::find(it, contents.end(), '\n'); |
---|
| 94 | |
---|
| 95 | // one-line comment spanning the whole line |
---|
| 96 | // with no quotes and no "*/" pair |
---|
| 97 | // |
---|
| 98 | match_results<string::const_iterator> m; |
---|
| 99 | const string whole_line( line_start, past_line_content ); |
---|
| 100 | const bool filter_out = |
---|
| 101 | regex_search( line_start, past_line_content |
---|
| 102 | , m, boost::regex(one_line_comment_line) ) |
---|
| 103 | && string::npos == whole_line.find('\"') |
---|
| 104 | && string::npos == whole_line.find("*/") |
---|
| 105 | ; |
---|
| 106 | |
---|
| 107 | if (!filter_out) { |
---|
| 108 | |
---|
| 109 | ++m_errors; |
---|
| 110 | error( library_name, full_path, string(name()) |
---|
| 111 | + " violation of Boost min/max guidelines on line " |
---|
| 112 | + boost::lexical_cast<string>( line_number ) ); |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | } |
---|
| 116 | } |
---|
| 117 | |
---|
| 118 | } // namespace inspect |
---|
| 119 | } // namespace boost |
---|
| 120 | |
---|