[29] | 1 | // inspect program ---------------------------------------------------------// |
---|
| 2 | |
---|
| 3 | // Copyright Beman Dawes 2002. |
---|
| 4 | // Copyright Rene Rivera 2004-2006. |
---|
| 5 | // Copyright Gennaro Prota 2006. |
---|
| 6 | |
---|
| 7 | // Distributed under the Boost Software License, Version 1.0. |
---|
| 8 | // (See accompanying file LICENSE_1_0.txt or copy at |
---|
| 9 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
| 10 | |
---|
| 11 | // This program recurses through sub-directories looking for various problems. |
---|
| 12 | // It contains some Boost specific features, like ignoring "CVS" and "bin", |
---|
| 13 | // and the code that identifies library names assumes the Boost directory |
---|
| 14 | // structure. |
---|
| 15 | |
---|
| 16 | // See http://www.boost.org/tools/inspect/ for more information. |
---|
| 17 | |
---|
| 18 | |
---|
| 19 | #include <vector> |
---|
| 20 | #include <list> |
---|
| 21 | #include <algorithm> |
---|
| 22 | #include <cstring> |
---|
| 23 | |
---|
| 24 | #include "boost/shared_ptr.hpp" |
---|
| 25 | #include "boost/filesystem/operations.hpp" |
---|
| 26 | #include "boost/filesystem/fstream.hpp" |
---|
| 27 | |
---|
| 28 | #include "time_string.hpp" |
---|
| 29 | |
---|
| 30 | #include "inspector.hpp" |
---|
| 31 | |
---|
| 32 | // the inspectors |
---|
| 33 | #include "copyright_check.hpp" |
---|
| 34 | #include "crlf_check.hpp" |
---|
| 35 | #include "license_check.hpp" |
---|
| 36 | #include "link_check.hpp" |
---|
| 37 | #include "long_name_check.hpp" |
---|
| 38 | #include "tab_check.hpp" |
---|
| 39 | #include "minmax_check.hpp" |
---|
| 40 | #include "unnamed_namespace_check.hpp" |
---|
| 41 | |
---|
| 42 | #include "cvs_iterator.hpp" |
---|
| 43 | |
---|
| 44 | #include "boost/test/included/prg_exec_monitor.hpp" |
---|
| 45 | |
---|
| 46 | namespace fs = boost::filesystem; |
---|
| 47 | |
---|
| 48 | namespace |
---|
| 49 | { |
---|
| 50 | class inspector_element |
---|
| 51 | { |
---|
| 52 | typedef boost::shared_ptr< boost::inspect::inspector > inspector_ptr; |
---|
| 53 | |
---|
| 54 | public: |
---|
| 55 | inspector_ptr inspector; |
---|
| 56 | explicit |
---|
| 57 | inspector_element( boost::inspect::inspector * p ) : inspector(p) {} |
---|
| 58 | }; |
---|
| 59 | |
---|
| 60 | typedef std::list< inspector_element > inspector_list; |
---|
| 61 | |
---|
| 62 | long file_count = 0; |
---|
| 63 | long directory_count = 0; |
---|
| 64 | long error_count = 0; |
---|
| 65 | |
---|
| 66 | boost::inspect::string_set content_signatures; |
---|
| 67 | |
---|
| 68 | struct error_msg |
---|
| 69 | { |
---|
| 70 | string library; |
---|
| 71 | string rel_path; |
---|
| 72 | string msg; |
---|
| 73 | |
---|
| 74 | bool operator<( const error_msg & rhs ) const |
---|
| 75 | { |
---|
| 76 | if ( library < rhs.library ) return true; |
---|
| 77 | if ( library > rhs.library ) return false; |
---|
| 78 | if ( rel_path < rhs.rel_path ) return true; |
---|
| 79 | if ( rel_path > rhs.rel_path ) return false; |
---|
| 80 | return msg < rhs.msg; |
---|
| 81 | } |
---|
| 82 | }; |
---|
| 83 | |
---|
| 84 | typedef std::vector< error_msg > error_msg_vector; |
---|
| 85 | error_msg_vector msgs; |
---|
| 86 | |
---|
| 87 | // visit_predicate (determines which directories are visited) --------------// |
---|
| 88 | |
---|
| 89 | typedef bool(*pred_type)(const path&); |
---|
| 90 | |
---|
| 91 | bool visit_predicate( const path & pth ) |
---|
| 92 | { |
---|
| 93 | string local( boost::inspect::relative_to( pth, fs::initial_path() ) ); |
---|
| 94 | string leaf( pth.leaf() ); |
---|
| 95 | return |
---|
| 96 | // so we can inspect a checkout |
---|
| 97 | leaf != "CVS" |
---|
| 98 | // don't look at binaries |
---|
| 99 | && leaf != "bin" |
---|
| 100 | && leaf != "bin.v2" |
---|
| 101 | // this really out of our hands |
---|
| 102 | && leaf != "jam_src" |
---|
| 103 | && local.find("tools/jam/src") != 0 |
---|
| 104 | // too many issues with generated HTML files |
---|
| 105 | && leaf != "status" |
---|
| 106 | // no point in checking doxygen xml output |
---|
| 107 | && local.find("doc/xml") != 0 |
---|
| 108 | // ignore some web files |
---|
| 109 | && leaf != ".htaccess" |
---|
| 110 | ; |
---|
| 111 | } |
---|
| 112 | |
---|
| 113 | // library_from_content ----------------------------------------------------// |
---|
| 114 | |
---|
| 115 | string library_from_content( const string & content ) |
---|
| 116 | { |
---|
| 117 | const string unknown_library ( "unknown" ); |
---|
| 118 | const string lib_root ( "www.boost.org/libs/" ); |
---|
| 119 | string::size_type pos( content.find( lib_root ) ); |
---|
| 120 | |
---|
| 121 | string lib = unknown_library; |
---|
| 122 | |
---|
| 123 | if ( pos != string::npos ) { |
---|
| 124 | |
---|
| 125 | pos += lib_root.length(); |
---|
| 126 | |
---|
| 127 | const char delims[] = " " // space and... |
---|
| 128 | "/\n\r\t"; |
---|
| 129 | |
---|
| 130 | string::size_type n = content.find_first_of( string(delims), pos ); |
---|
| 131 | if (n != string::npos) |
---|
| 132 | lib = string(content, pos, n - pos); |
---|
| 133 | |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | return lib; |
---|
| 137 | } |
---|
| 138 | |
---|
| 139 | // find_signature ----------------------------------------------------------// |
---|
| 140 | |
---|
| 141 | bool find_signature( const path & file_path, |
---|
| 142 | const boost::inspect::string_set & signatures ) |
---|
| 143 | { |
---|
| 144 | string name( file_path.leaf() ); |
---|
| 145 | if ( signatures.find( name ) == signatures.end() ) |
---|
| 146 | { |
---|
| 147 | string::size_type pos( name.rfind( '.' ) ); |
---|
| 148 | if ( pos == string::npos |
---|
| 149 | || signatures.find( name.substr( pos ) ) |
---|
| 150 | == signatures.end() ) return false; |
---|
| 151 | } |
---|
| 152 | return true; |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | // load_content ------------------------------------------------------------// |
---|
| 156 | |
---|
| 157 | void load_content( const path & file_path, string & target ) |
---|
| 158 | { |
---|
| 159 | target = ""; |
---|
| 160 | |
---|
| 161 | if ( !find_signature( file_path, content_signatures ) ) return; |
---|
| 162 | |
---|
| 163 | fs::ifstream fin( file_path, std::ios_base::in|std::ios_base::binary ); |
---|
| 164 | if ( !fin ) |
---|
| 165 | throw string( "could not open input file: " ) + file_path.string(); |
---|
| 166 | std::getline( fin, target, '\0' ); // read the whole file |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | // check -------------------------------------------------------------------// |
---|
| 170 | |
---|
| 171 | void check( const string & lib, |
---|
| 172 | const path & pth, const string & content, const inspector_list & insp_list ) |
---|
| 173 | { |
---|
| 174 | // invoke each inspector |
---|
| 175 | for ( inspector_list::const_iterator itr = insp_list.begin(); |
---|
| 176 | itr != insp_list.end(); ++itr ) |
---|
| 177 | { |
---|
| 178 | itr->inspector->inspect( lib, pth ); // always call two-argument form |
---|
| 179 | if ( find_signature( pth, itr->inspector->signatures() ) ) |
---|
| 180 | { |
---|
| 181 | itr->inspector->inspect( lib, pth, content ); |
---|
| 182 | } |
---|
| 183 | } |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | // visit_all ---------------------------------------------------------------// |
---|
| 187 | |
---|
| 188 | template< class DirectoryIterator > |
---|
| 189 | void visit_all( const string & lib, |
---|
| 190 | const path & dir_path, const inspector_list & insps ) |
---|
| 191 | { |
---|
| 192 | static DirectoryIterator end_itr; |
---|
| 193 | ++directory_count; |
---|
| 194 | |
---|
| 195 | for ( DirectoryIterator itr( dir_path ); itr != end_itr; ++itr ) |
---|
| 196 | { |
---|
| 197 | |
---|
| 198 | if ( fs::is_directory( *itr ) ) |
---|
| 199 | { |
---|
| 200 | if ( visit_predicate( *itr ) ) |
---|
| 201 | { |
---|
| 202 | string cur_lib( boost::inspect::impute_library( *itr ) ); |
---|
| 203 | check( cur_lib, *itr, "", insps ); |
---|
| 204 | visit_all<DirectoryIterator>( cur_lib, *itr, insps ); |
---|
| 205 | } |
---|
| 206 | } |
---|
| 207 | else |
---|
| 208 | { |
---|
| 209 | ++file_count; |
---|
| 210 | string content; |
---|
| 211 | load_content( *itr, content ); |
---|
| 212 | check( lib.empty() |
---|
| 213 | ? library_from_content( content ) : lib |
---|
| 214 | , *itr, content, insps ); |
---|
| 215 | } |
---|
| 216 | } |
---|
| 217 | } |
---|
| 218 | |
---|
| 219 | // display -----------------------------------------------------------------// |
---|
| 220 | |
---|
| 221 | enum display_format_type |
---|
| 222 | { |
---|
| 223 | display_html, display_text |
---|
| 224 | } |
---|
| 225 | display_format = display_html; |
---|
| 226 | |
---|
| 227 | enum display_mode_type |
---|
| 228 | { |
---|
| 229 | display_full, display_brief |
---|
| 230 | } |
---|
| 231 | display_mode = display_full; |
---|
| 232 | |
---|
| 233 | // display_summary_helper --------------------------------------------------// |
---|
| 234 | |
---|
| 235 | void display_summary_helper( const string & current_library, int err_count ) |
---|
| 236 | { |
---|
| 237 | if (display_text == display_format) |
---|
| 238 | { |
---|
| 239 | std::cout << " " << current_library << " (" << err_count << ")\n"; |
---|
| 240 | } |
---|
| 241 | else |
---|
| 242 | { |
---|
| 243 | std::cout |
---|
| 244 | << " <tr><td><a href=\"#" |
---|
| 245 | << current_library // what about malformed for URI refs? [gps] |
---|
| 246 | << "\">" << current_library |
---|
| 247 | << "</a></td><td align=\"center\">" |
---|
| 248 | << err_count << "</td></tr>\n"; |
---|
| 249 | } |
---|
| 250 | } |
---|
| 251 | |
---|
| 252 | // display_summary ---------------------------------------------------------// |
---|
| 253 | |
---|
| 254 | void display_summary() |
---|
| 255 | { |
---|
| 256 | if (display_text == display_format) |
---|
| 257 | { |
---|
| 258 | std::cout << "Summary:\n"; |
---|
| 259 | } |
---|
| 260 | else |
---|
| 261 | { |
---|
| 262 | std::cout |
---|
| 263 | << "</pre>\n" |
---|
| 264 | "<h2>Summary</h2>\n" |
---|
| 265 | "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n" |
---|
| 266 | " <tr>\n" |
---|
| 267 | " <td><b>Library</b></td>\n" |
---|
| 268 | " <td><b>Problems</b></td>\n" |
---|
| 269 | " </tr>\n" |
---|
| 270 | ; |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | string current_library( msgs.begin()->library ); |
---|
| 274 | int err_count = 0; |
---|
| 275 | for ( error_msg_vector::iterator itr ( msgs.begin() ); |
---|
| 276 | itr != msgs.end(); ++itr ) |
---|
| 277 | { |
---|
| 278 | if ( current_library != itr->library ) |
---|
| 279 | { |
---|
| 280 | display_summary_helper( current_library, err_count ); |
---|
| 281 | current_library = itr->library; |
---|
| 282 | err_count = 0; |
---|
| 283 | } |
---|
| 284 | ++err_count; |
---|
| 285 | } |
---|
| 286 | display_summary_helper( current_library, err_count ); |
---|
| 287 | |
---|
| 288 | if (display_text == display_format) |
---|
| 289 | { |
---|
| 290 | std::cout << "\n"; |
---|
| 291 | } |
---|
| 292 | else |
---|
| 293 | { |
---|
| 294 | std::cout << "</table>\n"; |
---|
| 295 | } |
---|
| 296 | } |
---|
| 297 | |
---|
| 298 | |
---|
| 299 | // display_details ---------------------------------------------------------// |
---|
| 300 | |
---|
| 301 | void display_details() |
---|
| 302 | { |
---|
| 303 | // gps - review this |
---|
| 304 | |
---|
| 305 | if (display_text == display_format) |
---|
| 306 | { |
---|
| 307 | // display error messages with group indication |
---|
| 308 | error_msg current; |
---|
| 309 | string sep; |
---|
| 310 | for ( error_msg_vector::iterator itr ( msgs.begin() ); |
---|
| 311 | itr != msgs.end(); ++itr ) |
---|
| 312 | { |
---|
| 313 | if ( current.library != itr->library ) |
---|
| 314 | { |
---|
| 315 | if ( display_full == display_mode ) |
---|
| 316 | std::cout << "\n|" << itr->library << "|\n"; |
---|
| 317 | else |
---|
| 318 | std::cout << "\n\n|" << itr->library << '|'; |
---|
| 319 | } |
---|
| 320 | |
---|
| 321 | if ( current.library != itr->library |
---|
| 322 | || current.rel_path != itr->rel_path ) |
---|
| 323 | { |
---|
| 324 | if ( display_full == display_mode ) |
---|
| 325 | { |
---|
| 326 | std::cout << " " << itr->rel_path << ":\n"; |
---|
| 327 | } |
---|
| 328 | else |
---|
| 329 | { |
---|
| 330 | path current_rel_path(current.rel_path); |
---|
| 331 | path this_rel_path(itr->rel_path); |
---|
| 332 | if (current_rel_path.branch_path() != this_rel_path.branch_path()) |
---|
| 333 | { |
---|
| 334 | std::cout << "\n " << this_rel_path.branch_path().string() << '/'; |
---|
| 335 | } |
---|
| 336 | std::cout << "\n " << this_rel_path.leaf() << ':'; |
---|
| 337 | } |
---|
| 338 | } |
---|
| 339 | if ( current.library != itr->library |
---|
| 340 | || current.rel_path != itr->rel_path |
---|
| 341 | || current.msg != itr->msg ) |
---|
| 342 | { |
---|
| 343 | const string m = itr->msg; |
---|
| 344 | |
---|
| 345 | if ( display_full == display_mode ) |
---|
| 346 | std::cout << " " << m << '\n'; |
---|
| 347 | else |
---|
| 348 | std::cout << ' ' << m; |
---|
| 349 | } |
---|
| 350 | current.library = itr->library; |
---|
| 351 | current.rel_path = itr->rel_path; |
---|
| 352 | current.msg = itr->msg; |
---|
| 353 | } |
---|
| 354 | std::cout << "\n"; |
---|
| 355 | } |
---|
| 356 | else |
---|
| 357 | { |
---|
| 358 | // display error messages with group indication |
---|
| 359 | error_msg current; |
---|
| 360 | string sep; |
---|
| 361 | bool first = true; |
---|
| 362 | for ( error_msg_vector::iterator itr ( msgs.begin() ); |
---|
| 363 | itr != msgs.end(); ++itr ) |
---|
| 364 | { |
---|
| 365 | if ( current.library != itr->library ) |
---|
| 366 | { |
---|
| 367 | if ( !first ) std::cout << "</pre>\n"; |
---|
| 368 | std::cout << "\n<h3><a name=\"" << itr->library |
---|
| 369 | << "\">" << itr->library << "</a></h3>\n<pre>"; |
---|
| 370 | } |
---|
| 371 | if ( current.library != itr->library |
---|
| 372 | || current.rel_path != itr->rel_path ) |
---|
| 373 | { |
---|
| 374 | std::cout << "\n"; |
---|
| 375 | std::cout << itr->rel_path; |
---|
| 376 | sep = ": "; |
---|
| 377 | } |
---|
| 378 | if ( current.library != itr->library |
---|
| 379 | || current.rel_path != itr->rel_path |
---|
| 380 | || current.msg != itr->msg ) |
---|
| 381 | { |
---|
| 382 | std::cout << sep << itr->msg; |
---|
| 383 | sep = ", "; |
---|
| 384 | } |
---|
| 385 | current.library = itr->library; |
---|
| 386 | current.rel_path = itr->rel_path; |
---|
| 387 | current.msg = itr->msg; |
---|
| 388 | first = false; |
---|
| 389 | } |
---|
| 390 | std::cout << "</pre>\n"; |
---|
| 391 | } |
---|
| 392 | } |
---|
| 393 | |
---|
| 394 | const char * options() |
---|
| 395 | { |
---|
| 396 | return |
---|
| 397 | " -license\n" |
---|
| 398 | " -copyright\n" |
---|
| 399 | " -crlf\n" |
---|
| 400 | " -link\n" |
---|
| 401 | " -long_name\n" |
---|
| 402 | " -tab\n" |
---|
| 403 | " -minmax\n" |
---|
| 404 | " -unnamed\n" |
---|
| 405 | " default is all checks on; otherwise options specify desired checks" |
---|
| 406 | "\n"; |
---|
| 407 | } |
---|
| 408 | |
---|
| 409 | const char * doctype_declaration() |
---|
| 410 | { |
---|
| 411 | return |
---|
| 412 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" |
---|
| 413 | "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" |
---|
| 414 | ; |
---|
| 415 | } |
---|
| 416 | |
---|
| 417 | std::string validator_link(const std::string & text) |
---|
| 418 | { |
---|
| 419 | return |
---|
| 420 | // with link to validation service |
---|
| 421 | "<a href=\"http://validator.w3.org/check?uri=referer\">" |
---|
| 422 | + text |
---|
| 423 | + "</a>" |
---|
| 424 | ; |
---|
| 425 | } |
---|
| 426 | |
---|
| 427 | } // unnamed namespace |
---|
| 428 | |
---|
| 429 | namespace boost |
---|
| 430 | { |
---|
| 431 | namespace inspect |
---|
| 432 | { |
---|
| 433 | |
---|
| 434 | // register_signature ------------------------------------------------------// |
---|
| 435 | |
---|
| 436 | void inspector::register_signature( const string & signature ) |
---|
| 437 | { |
---|
| 438 | m_signatures.insert( signature ); |
---|
| 439 | content_signatures.insert( signature ); |
---|
| 440 | } |
---|
| 441 | |
---|
| 442 | // error -------------------------------------------------------------------// |
---|
| 443 | |
---|
| 444 | void inspector::error( const string & library_name, |
---|
| 445 | const path & full_path, const string & msg ) |
---|
| 446 | { |
---|
| 447 | ++error_count; |
---|
| 448 | error_msg err_msg; |
---|
| 449 | err_msg.library = library_name; |
---|
| 450 | err_msg.rel_path = relative_to( full_path, fs::initial_path() ); |
---|
| 451 | err_msg.msg = msg; |
---|
| 452 | msgs.push_back( err_msg ); |
---|
| 453 | |
---|
| 454 | // std::cout << library_name << ": " |
---|
| 455 | // << full_path.string() << ": " |
---|
| 456 | // << msg << '\n'; |
---|
| 457 | |
---|
| 458 | } |
---|
| 459 | |
---|
| 460 | source_inspector::source_inspector() |
---|
| 461 | { |
---|
| 462 | // C/C++ source code... |
---|
| 463 | register_signature( ".c" ); |
---|
| 464 | register_signature( ".cpp" ); |
---|
| 465 | register_signature( ".css" ); |
---|
| 466 | register_signature( ".cxx" ); |
---|
| 467 | register_signature( ".h" ); |
---|
| 468 | register_signature( ".hpp" ); |
---|
| 469 | register_signature( ".hxx" ); |
---|
| 470 | register_signature( ".inc" ); |
---|
| 471 | register_signature( ".ipp" ); |
---|
| 472 | |
---|
| 473 | // Boost.Build BJam source code... |
---|
| 474 | register_signature( "Jamfile" ); |
---|
| 475 | register_signature( ".jam" ); |
---|
| 476 | register_signature( ".v2" ); |
---|
| 477 | |
---|
| 478 | // Other scripts; Python, shell, autoconfig, etc. |
---|
| 479 | register_signature( "configure.in" ); |
---|
| 480 | register_signature( "GNUmakefile" ); |
---|
| 481 | register_signature( "Makefile" ); |
---|
| 482 | register_signature( ".bat" ); |
---|
| 483 | register_signature( ".mak" ); |
---|
| 484 | register_signature( ".pl" ); |
---|
| 485 | register_signature( ".py" ); |
---|
| 486 | register_signature( ".sh" ); |
---|
| 487 | |
---|
| 488 | // Hypertext, Boost.Book, and other text... |
---|
| 489 | register_signature( "news" ); |
---|
| 490 | register_signature( "readme" ); |
---|
| 491 | register_signature( "todo" ); |
---|
| 492 | register_signature( "NEWS" ); |
---|
| 493 | register_signature( "README" ); |
---|
| 494 | register_signature( "TODO" ); |
---|
| 495 | register_signature( ".boostbook" ); |
---|
| 496 | register_signature( ".htm" ); |
---|
| 497 | register_signature( ".html" ); |
---|
| 498 | register_signature( ".rst" ); |
---|
| 499 | register_signature( ".sgml" ); |
---|
| 500 | register_signature( ".shtml" ); |
---|
| 501 | register_signature( ".txt" ); |
---|
| 502 | register_signature( ".xml" ); |
---|
| 503 | register_signature( ".xsd" ); |
---|
| 504 | register_signature( ".xsl" ); |
---|
| 505 | } |
---|
| 506 | |
---|
| 507 | hypertext_inspector::hypertext_inspector() |
---|
| 508 | { |
---|
| 509 | register_signature( ".htm" ); |
---|
| 510 | register_signature( ".html" ); |
---|
| 511 | register_signature( ".shtml" ); |
---|
| 512 | } |
---|
| 513 | |
---|
| 514 | // impute_library ----------------------------------------------------------// |
---|
| 515 | |
---|
| 516 | // may return an empty string [gps] |
---|
| 517 | string impute_library( const path & full_dir_path ) |
---|
| 518 | { |
---|
| 519 | path relative( relative_to( full_dir_path, fs::initial_path() ), |
---|
| 520 | fs::no_check ); |
---|
| 521 | if ( relative.empty() ) return "boost-root"; |
---|
| 522 | string first( *relative.begin() ); |
---|
| 523 | string second = // borland 5.61 requires op= |
---|
| 524 | ++relative.begin() == relative.end() |
---|
| 525 | ? string() : *++relative.begin(); |
---|
| 526 | |
---|
| 527 | if ( first == "boost" ) |
---|
| 528 | return second; |
---|
| 529 | |
---|
| 530 | return (( first == "libs" || first == "tools" ) && !second.empty()) |
---|
| 531 | ? second : first; |
---|
| 532 | } |
---|
| 533 | |
---|
| 534 | } // namespace inspect |
---|
| 535 | } // namespace boost |
---|
| 536 | |
---|
| 537 | // cpp_main() --------------------------------------------------------------// |
---|
| 538 | |
---|
| 539 | int cpp_main( int argc_param, char * argv_param[] ) |
---|
| 540 | { |
---|
| 541 | // <hack> for the moment, let's be on the safe side |
---|
| 542 | // and ensure we don't modify anything being pointed to; |
---|
| 543 | // then we'll do some cleanup here |
---|
| 544 | int argc = argc_param; |
---|
| 545 | const char* const * argv = &argv_param[0]; |
---|
| 546 | |
---|
| 547 | if ( argc > 1 && (std::strcmp( argv[1], "-help" ) == 0 |
---|
| 548 | || std::strcmp( argv[1], "--help" ) == 0 ) ) |
---|
| 549 | { |
---|
| 550 | std::clog << "Usage: inspect [-cvs] [-text] [-brief] [options...]\n\n" |
---|
| 551 | " Options:\n" |
---|
| 552 | << options() << '\n'; |
---|
| 553 | return 0; |
---|
| 554 | } |
---|
| 555 | |
---|
| 556 | bool license_ck = true; |
---|
| 557 | bool copyright_ck = true; |
---|
| 558 | bool crlf_ck = true; |
---|
| 559 | bool link_ck = true; |
---|
| 560 | bool long_name_ck = true; |
---|
| 561 | bool tab_ck = true; |
---|
| 562 | bool minmax_ck = true; |
---|
| 563 | bool unnamed_ck = true; |
---|
| 564 | bool cvs = false; |
---|
| 565 | |
---|
| 566 | if ( argc > 1 && std::strcmp( argv[1], "-cvs" ) == 0 ) |
---|
| 567 | { |
---|
| 568 | cvs = true; |
---|
| 569 | --argc; ++argv; |
---|
| 570 | } |
---|
| 571 | |
---|
| 572 | if ( argc > 1 && std::strcmp( argv[1], "-text" ) == 0 ) |
---|
| 573 | { |
---|
| 574 | display_format = display_text; |
---|
| 575 | --argc; ++argv; |
---|
| 576 | } |
---|
| 577 | |
---|
| 578 | if ( argc > 1 && std::strcmp( argv[1], "-brief" ) == 0 ) |
---|
| 579 | { |
---|
| 580 | display_mode = display_brief; |
---|
| 581 | --argc; ++argv; |
---|
| 582 | } |
---|
| 583 | |
---|
| 584 | if ( argc > 1 && *argv[1] == '-' ) |
---|
| 585 | { |
---|
| 586 | license_ck = false; |
---|
| 587 | copyright_ck = false; |
---|
| 588 | crlf_ck = false; |
---|
| 589 | link_ck = false; |
---|
| 590 | long_name_ck = false; |
---|
| 591 | tab_ck = false; |
---|
| 592 | minmax_ck = false; |
---|
| 593 | unnamed_ck = false; |
---|
| 594 | } |
---|
| 595 | |
---|
| 596 | bool invalid_options = false; |
---|
| 597 | for(; argc > 1; --argc, ++argv ) |
---|
| 598 | { |
---|
| 599 | if ( std::strcmp( argv[1], "-license" ) == 0 ) |
---|
| 600 | license_ck = true; |
---|
| 601 | else if ( std::strcmp( argv[1], "-copyright" ) == 0 ) |
---|
| 602 | copyright_ck = true; |
---|
| 603 | else if ( std::strcmp( argv[1], "-crlf" ) == 0 ) |
---|
| 604 | crlf_ck = true; |
---|
| 605 | else if ( std::strcmp( argv[1], "-link" ) == 0 ) |
---|
| 606 | link_ck = true; |
---|
| 607 | else if ( std::strcmp( argv[1], "-long_name" ) == 0 ) |
---|
| 608 | long_name_ck = true; |
---|
| 609 | else if ( std::strcmp( argv[1], "-tab" ) == 0 ) |
---|
| 610 | tab_ck = true; |
---|
| 611 | else if ( std::strcmp( argv[1], "-minmax" ) == 0 ) |
---|
| 612 | minmax_ck = true; |
---|
| 613 | else if ( std::strcmp( argv[1], "-unnamed" ) == 0 ) |
---|
| 614 | unnamed_ck = true; |
---|
| 615 | else |
---|
| 616 | { |
---|
| 617 | std::cerr << "unknown option: " << argv[1] << '\n'; |
---|
| 618 | invalid_options = true; |
---|
| 619 | } |
---|
| 620 | } |
---|
| 621 | if ( invalid_options ) { |
---|
| 622 | std::cerr << "\nvalid options are:\n" |
---|
| 623 | << options(); |
---|
| 624 | return 1; |
---|
| 625 | } |
---|
| 626 | |
---|
| 627 | string inspector_keys; |
---|
| 628 | fs::initial_path(); |
---|
| 629 | |
---|
| 630 | { |
---|
| 631 | |
---|
| 632 | // note how this is in its own block; reporting will happen |
---|
| 633 | // automatically, from each registered inspector, when |
---|
| 634 | // leaving, due to destruction of the inspector_list object |
---|
| 635 | inspector_list inspectors; |
---|
| 636 | |
---|
| 637 | if ( license_ck ) |
---|
| 638 | inspectors.push_back( inspector_element( new boost::inspect::license_check ) ); |
---|
| 639 | if ( copyright_ck ) |
---|
| 640 | inspectors.push_back( inspector_element( new boost::inspect::copyright_check ) ); |
---|
| 641 | if ( crlf_ck ) |
---|
| 642 | inspectors.push_back( inspector_element( new boost::inspect::crlf_check ) ); |
---|
| 643 | if ( link_ck ) |
---|
| 644 | inspectors.push_back( inspector_element( new boost::inspect::link_check ) ); |
---|
| 645 | if ( long_name_ck ) |
---|
| 646 | inspectors.push_back( inspector_element( new boost::inspect::file_name_check ) ); |
---|
| 647 | if ( tab_ck ) |
---|
| 648 | inspectors.push_back( inspector_element( new boost::inspect::tab_check ) ); |
---|
| 649 | if ( minmax_ck ) |
---|
| 650 | inspectors.push_back( inspector_element( new boost::inspect::minmax_check ) ); |
---|
| 651 | if ( unnamed_ck ) |
---|
| 652 | inspectors.push_back( inspector_element( new boost::inspect::unnamed_namespace_check ) ); |
---|
| 653 | |
---|
| 654 | // perform the actual inspection, using the requested type of iteration |
---|
| 655 | if ( cvs ) |
---|
| 656 | visit_all<hack::cvs_iterator>( "boost-root", |
---|
| 657 | fs::initial_path(), inspectors ); |
---|
| 658 | else |
---|
| 659 | visit_all<fs::directory_iterator>( "boost-root", |
---|
| 660 | fs::initial_path(), inspectors ); |
---|
| 661 | |
---|
| 662 | // close |
---|
| 663 | for ( inspector_list::iterator itr = inspectors.begin(); |
---|
| 664 | itr != inspectors.end(); ++itr ) |
---|
| 665 | { |
---|
| 666 | itr->inspector->close(); |
---|
| 667 | } |
---|
| 668 | |
---|
| 669 | string run_date ( "n/a" ); |
---|
| 670 | boost::time_string( run_date ); |
---|
| 671 | |
---|
| 672 | if (display_text == display_format) |
---|
| 673 | { |
---|
| 674 | std::cout |
---|
| 675 | << |
---|
| 676 | "Boost Inspection Report\n" |
---|
| 677 | "Run Date: " << run_date << "\n" |
---|
| 678 | "\n" |
---|
| 679 | "An inspection program <http://www.boost.org/tools/inspect/index.html>\n" |
---|
| 680 | "checks each file in the current Boost CVS for various problems,\n" |
---|
| 681 | "generating this as output. Problems detected include tabs in files,\n" |
---|
| 682 | "missing copyrights, broken URL's, and similar misdemeanors.\n" |
---|
| 683 | "\n" |
---|
| 684 | ; |
---|
| 685 | |
---|
| 686 | std::cout |
---|
| 687 | << "Totals:\n" |
---|
| 688 | << " " << file_count << " files scanned\n" |
---|
| 689 | << " " << directory_count << " directories scanned (including root)\n" |
---|
| 690 | << " " << error_count << " problems reported\n" |
---|
| 691 | << '\n' |
---|
| 692 | ; |
---|
| 693 | } |
---|
| 694 | else |
---|
| 695 | { |
---|
| 696 | // |
---|
| 697 | std::cout << doctype_declaration() << '\n'; |
---|
| 698 | |
---|
| 699 | std::cout |
---|
| 700 | << "<html>\n" |
---|
| 701 | "<head>\n" |
---|
| 702 | "<title>Boost Inspection Report</title>\n" |
---|
| 703 | "</head>\n" |
---|
| 704 | |
---|
| 705 | "<body>\n" |
---|
| 706 | // we should not use a table, of course [gps] |
---|
| 707 | "<table>\n" |
---|
| 708 | "<tr>\n" |
---|
| 709 | "<td><img src=\"../boost.png\" alt=\"Boost logo\" />" |
---|
| 710 | "</td>\n" |
---|
| 711 | "<td>\n" |
---|
| 712 | "<h1>Boost Inspection Report</h1>\n" |
---|
| 713 | "<b>Run Date:</b> " << run_date << "\n" |
---|
| 714 | " / " << validator_link( "validate me" ) << " /\n" |
---|
| 715 | "</td>\n" |
---|
| 716 | "</tr>\n" |
---|
| 717 | "</table>\n" |
---|
| 718 | |
---|
| 719 | "<p>An <a href=\"http://www.boost.org/tools/inspect/index.html\">inspection\n" |
---|
| 720 | "program</a> checks each file in the current Boost CVS for various problems,\n" |
---|
| 721 | "generating this web page as output. Problems detected include tabs in files,\n" |
---|
| 722 | "missing copyrights, broken URL's, and similar misdemeanors.</p>\n" |
---|
| 723 | ; |
---|
| 724 | |
---|
| 725 | std::cout |
---|
| 726 | << "<h2>Totals</h2>\n<pre>" |
---|
| 727 | << file_count << " files scanned\n" |
---|
| 728 | << directory_count << " directories scanned (including root)\n" |
---|
| 729 | << error_count << " problems reported\n"; |
---|
| 730 | } |
---|
| 731 | |
---|
| 732 | for ( inspector_list::iterator itr = inspectors.begin(); |
---|
| 733 | itr != inspectors.end(); ++itr ) |
---|
| 734 | { |
---|
| 735 | const string line_break ( |
---|
| 736 | display_text == display_format? "\n" : "<br />\n"); // gps |
---|
| 737 | |
---|
| 738 | inspector_keys += static_cast<string>(" ") |
---|
| 739 | + itr->inspector->name() |
---|
| 740 | + ' ' + itr->inspector->desc() |
---|
| 741 | + line_break |
---|
| 742 | ; |
---|
| 743 | } |
---|
| 744 | |
---|
| 745 | |
---|
| 746 | std::cout |
---|
| 747 | << "\nProblem counts:\n"; |
---|
| 748 | |
---|
| 749 | } // end of block: starts reporting |
---|
| 750 | |
---|
| 751 | if (display_text == display_format) |
---|
| 752 | { |
---|
| 753 | std::cout << "\n" ; |
---|
| 754 | } |
---|
| 755 | |
---|
| 756 | std::sort( msgs.begin(), msgs.end() ); |
---|
| 757 | |
---|
| 758 | if ( !msgs.empty() ) |
---|
| 759 | { |
---|
| 760 | display_summary(); |
---|
| 761 | |
---|
| 762 | if (display_text == display_format) |
---|
| 763 | { |
---|
| 764 | std::cout << "Details:\n" << inspector_keys; |
---|
| 765 | } |
---|
| 766 | else |
---|
| 767 | { |
---|
| 768 | std::cout << "<h2>Details</h2>\n" << inspector_keys; |
---|
| 769 | } |
---|
| 770 | display_details(); |
---|
| 771 | } |
---|
| 772 | |
---|
| 773 | if (display_text == display_format) |
---|
| 774 | { |
---|
| 775 | std::cout << "\n\n" ; |
---|
| 776 | } |
---|
| 777 | else |
---|
| 778 | { |
---|
| 779 | std::cout |
---|
| 780 | << "</body>\n" |
---|
| 781 | "</html>\n"; |
---|
| 782 | } |
---|
| 783 | |
---|
| 784 | return 0; |
---|
| 785 | } |
---|