| 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 | } |
|---|