Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/inspect/inspect.cpp @ 14

Last change on this file since 14 was 12, checked in by landauf, 18 years ago

added boost

File size: 15.6 KB
Line 
1//  inspect program  ---------------------------------------------------------//
2
3//  Copyright Beman Dawes 2002.
4//  Copyright Rene Rivera 2004.
5//  Distributed under the Boost Software License, Version 1.0.
6//  (See accompanying file LICENSE_1_0.txt or copy at
7//  http://www.boost.org/LICENSE_1_0.txt)
8
9//  This program recurses through sub-directories looking for various problems.
10//  It contains some Boost specific features, like ignoring "CVS" and "bin",
11//  and the code that identifies library names assumes the Boost directory
12//  structure.
13
14//  See http://www.boost.org/tools/inspect for more information.
15
16#include <boost/shared_ptr.hpp>
17#include <boost/filesystem/exception.hpp>
18#include <boost/filesystem/operations.hpp>
19#include <boost/filesystem/fstream.hpp>
20
21#include <iostream>
22#include <cassert>
23#include <vector>
24#include <list>
25#include <utility>
26#include <algorithm>
27#include <cstring>
28
29#include "inspector.hpp" // includes <string>, <boost/filesystem/path.hpp>,
30                         // <iostream>, <set>
31                         // and gives using for string and path.
32#include "copyright_check.hpp"
33#include "crlf_check.hpp"
34#include "license_check.hpp"
35#include "link_check.hpp"
36#include "long_name_check.hpp"
37#include "tab_check.hpp"
38#include "minmax_check.hpp"
39#include "cvs_iterator.hpp"
40
41namespace fs = boost::filesystem;
42
43namespace
44{
45  typedef boost::shared_ptr< boost::inspect::inspector > inspector_ptr;
46
47  struct inspector_element
48  {
49    inspector_ptr  inspector;
50
51    inspector_element( boost::inspect::inspector * p ) : inspector(p) {}
52  };
53
54  typedef std::list< inspector_element > inspector_list;
55
56  long file_count;
57  long directory_count;
58  long error_count;
59
60  boost::inspect::string_set content_signatures;
61
62  struct error_msg
63  {
64    string library;
65    string rel_path;
66    string msg;
67
68    bool operator<( const error_msg & rhs ) const
69    {
70      if ( library < rhs.library ) return true;
71      if ( library > rhs.library ) return false;
72      if ( rel_path < rhs.rel_path ) return true;
73      if ( rel_path > rhs.rel_path ) return false;
74      return msg < rhs.msg;
75    }
76  };
77
78  typedef std::vector< error_msg > error_msg_vector;
79  error_msg_vector msgs;
80
81//  visit_predicate (determines which directories are visited)  --------------//
82
83  typedef bool(*pred_type)(const path&);
84
85  bool visit_predicate( const path & pth )
86  {
87    string leaf( pth.leaf() );
88    return
89      leaf != "CVS"
90      && leaf != "bin"
91      && leaf != "jam_src" // this really out of our hands
92      && leaf != "status"  // too many issues with generated HTML files
93      ;
94  }
95
96//  library_from_content  ----------------------------------------------------//
97
98  string library_from_content( const string & content )
99  {
100    string::size_type pos( content.find( "www.boost.org/libs/" ) );
101
102    if ( pos == string::npos ) return "unknown";
103
104    string lib;
105    pos += 19;
106    while ( content[pos] != ' '
107      && content[pos] != '/'
108      && content[pos] != '\n'
109      && content[pos] != '\r'
110      && content[pos] != '\t' ) lib += content[pos++];
111    return lib;
112  }
113
114//  find_signature  ----------------------------------------------------------//
115
116  bool find_signature( const path & file_path,
117    const boost::inspect::string_set & signatures )
118  {
119    string name( file_path.leaf() );
120    if ( signatures.find( name ) == signatures.end() )
121    {
122      string::size_type pos( name.rfind( '.' ) );
123      if ( pos == string::npos
124        || signatures.find( name.substr( pos ) )
125          == signatures.end() ) return false;
126    }
127    return true;
128  }
129
130//  load_content  ------------------------------------------------------------//
131
132  void load_content( const path & file_path, string & target )
133  {
134    target = "";
135
136    if ( !find_signature( file_path, content_signatures ) ) return;
137
138    fs::ifstream fin( file_path, std::ios_base::in|std::ios_base::binary );
139    if ( !fin )
140      throw string( "could not open input file: " ) + file_path.string();
141    std::getline( fin, target, '\0' ); // read the whole file
142  }
143
144//  check  -------------------------------------------------------------------//
145
146  void check( const string & lib,
147    const path & pth, const string & content, const inspector_list & insp_list )
148  {
149    // invoke each inspector
150    for ( inspector_list::const_iterator itr = insp_list.begin();
151      itr != insp_list.end(); ++itr )
152    {
153      itr->inspector->inspect( lib, pth ); // always call two-argument form
154      if ( find_signature( pth, itr->inspector->signatures() ) )
155      {
156          itr->inspector->inspect( lib, pth, content );
157      }
158    }
159  }
160
161//  visit_all  ---------------------------------------------------------------//
162
163  template< class DirectoryIterator >
164  void visit_all( const string & lib,
165    const path & dir_path, const inspector_list & insps )
166  {
167    static DirectoryIterator end_itr;
168    ++directory_count;
169
170    for ( DirectoryIterator itr( dir_path ); itr != end_itr; ++itr )
171    {
172
173      if ( fs::is_directory( *itr ) )
174      {
175        if ( visit_predicate( *itr ) )
176        {
177          string cur_lib( boost::inspect::impute_library( *itr ) );
178          check( cur_lib, *itr, "", insps );
179          visit_all<DirectoryIterator>( cur_lib, *itr, insps );
180        }
181      }
182      else
183      {
184        ++file_count;
185        string content;
186        load_content( *itr, content );
187        check( lib == "unknown"
188          ? library_from_content( content ) : lib, *itr, content, insps );
189      }
190    }
191  }
192
193//  display_summary_helper  --------------------------------------------------//
194
195  void display_summary_helper( const string & current_library, int err_count )
196  {
197    std::cout << "  <tr><td><a href=\"#" 
198              << current_library
199              << "\">" << current_library
200              << "</a></td><td align=\"center\">"
201              << err_count << "</td></tr>\n";
202  }
203 
204//  display_summary  ---------------------------------------------------------//
205
206  void display_summary()
207  {
208    std::cout << "</pre>\n"
209            "<h2>Summary</h2>\n"
210            "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n"
211            "  <tr>\n"
212            "    <td><b>Library</b></td>\n"
213            "    <td><b>Problems</b></td>\n"
214            "  </tr>\n"
215            ;
216    string current_library( msgs.begin()->library ); 
217    int err_count = 0;
218    for ( error_msg_vector::iterator itr ( msgs.begin() );
219      itr != msgs.end(); ++itr )
220    {
221      if ( current_library != itr->library )
222      {
223        display_summary_helper( current_library, err_count );
224        current_library = itr->library;
225        err_count = 0;
226      }
227      ++err_count;
228    }
229    display_summary_helper( current_library, err_count );
230
231    std::cout << "</table>\n";
232  }
233
234
235//  display_details  ---------------------------------------------------------//
236
237  void display_details()
238  {
239    std::cout << "<h2>Details</h2>\n";
240
241    // display error messages with group indication
242    error_msg current;
243    string sep;
244    bool first = true;
245    for ( error_msg_vector::iterator itr ( msgs.begin() );
246      itr != msgs.end(); ++itr )
247    {
248      if ( current.library != itr->library )
249      {
250        if ( !first ) std::cout << "</pre>\n";
251        std::cout << "\n<h3><a name=\"" << itr->library
252                  << "\">" << itr->library << "</a></h3>\n<pre>";
253      }
254      if ( current.library != itr->library
255        || current.rel_path != itr->rel_path )
256      {
257        std::cout << "\n";
258        std::cout << itr->rel_path;
259        sep = ": ";
260      }
261      if ( current.library != itr->library
262        || current.rel_path != itr->rel_path
263        || current.msg != itr->msg )
264      {
265        std::cout << sep << itr->msg;
266        sep = ", ";
267      }
268      current.library = itr->library;
269      current.rel_path = itr->rel_path;
270      current.msg = itr->msg;
271      first = false;
272   }
273   std::cout << "</pre>\n";
274  }
275
276  const char * options()
277  {
278    return
279         "  -license\n"
280         "  -copyright\n"
281         "  -crlf\n"
282         "  -link\n"
283         "  -long_name\n"
284         "  -tab\n"
285         "  -minmax\n"
286         "default is all checks on; otherwise options specify desired checks\n";
287  }
288
289} // unnamed namespace
290
291namespace boost
292{
293  namespace inspect
294  {
295
296//  register_signature  ------------------------------------------------------//
297
298    void inspector::register_signature( const string & signature )
299    {
300      m_signatures.insert( signature );
301      content_signatures.insert( signature );
302    }
303
304//  error  -------------------------------------------------------------------//
305
306    void inspector::error( const string & library_name,
307      const path & full_path, const string & msg )
308    {
309      ++error_count;
310      error_msg err_msg;
311      err_msg.library = library_name;
312      err_msg.rel_path = relative_to( full_path, fs::initial_path() );
313      err_msg.msg = msg;
314      msgs.push_back( err_msg );
315
316//     std::cout << library_name << ": "
317//        << full_path.string() << ": "
318//        << msg << '\n';
319
320    }
321   
322    source_inspector::source_inspector()
323    {
324      // C/C++ source code...
325      register_signature( ".c" );
326      register_signature( ".cpp" );
327      register_signature( ".css" );
328      register_signature( ".cxx" );
329      register_signature( ".h" );
330      register_signature( ".hpp" );
331      register_signature( ".hxx" );
332      register_signature( ".inc" );
333      register_signature( ".ipp" );
334     
335      // Boost.Build BJam source code...
336      register_signature( "Jamfile" );
337      register_signature( ".jam" );
338      register_signature( ".v2" );
339     
340      // Other scripts; Python, shell, autoconfig, etc.
341      register_signature( "configure.in" );
342      register_signature( "GNUmakefile" );
343      register_signature( "Makefile" );
344      register_signature( ".bat" );
345      register_signature( ".mak" );
346      register_signature( ".pl" );
347      register_signature( ".py" );
348      register_signature( ".sh" );
349     
350      // Hypertext, Boost.Book, and other text...
351      register_signature( "news" );
352      register_signature( "readme" );
353      register_signature( "todo" );
354      register_signature( "NEWS" );
355      register_signature( "README" );
356      register_signature( "TODO" );
357      register_signature( ".boostbook" );
358      register_signature( ".htm" );
359      register_signature( ".html" );
360      register_signature( ".rst" );
361      register_signature( ".sgml" );
362      register_signature( ".shtml" );
363      register_signature( ".txt" );
364      register_signature( ".xml" );
365      register_signature( ".xsd" );
366      register_signature( ".xsl" );
367    }
368   
369    hypertext_inspector::hypertext_inspector()
370    {
371      register_signature( ".htm" );
372      register_signature( ".html" );
373      register_signature( ".shtml" );
374    }
375
376//  impute_library  ----------------------------------------------------------//
377
378    string impute_library( const path & full_dir_path )
379    {
380      path relative( relative_to( full_dir_path, fs::initial_path() ),
381        fs::no_check );
382      if ( relative.empty() ) return "boost-root";
383      string first( *relative.begin() );
384      string second =  // borland 5.61 requires op= 
385        ++relative.begin() == relative.end()
386          ? string() : *++relative.begin();
387
388      if ( first == "boost" )
389        return second.empty() ? string( "unknown" ) : second;
390
391      return (( first == "libs" || first == "tools" ) && !second.empty())
392        ? second : first;
393    }
394
395  } // namespace inspect
396} // namespace boost
397
398//  cpp_main()  --------------------------------------------------------------//
399
400#include <boost/test/included/prg_exec_monitor.hpp>
401
402int cpp_main( int argc, char * argv[] )
403{
404  fs::initial_path();
405
406  if ( argc > 1 && (std::strcmp( argv[1], "-help" ) == 0
407    || std::strcmp( argv[1], "--help" ) == 0 ) )
408  {
409    std::clog << "Usage: inspect [-cvs] [options...]\n"
410      "options:\n"
411      << options();
412    return 1;
413  }
414
415  bool license_ck = true;
416  bool copyright_ck = true;
417  bool crlf_ck = true;
418  bool link_ck = true;
419  bool long_name_ck = true;
420  bool tab_ck = true;
421  bool minmax_ck = true;
422  bool cvs = false;
423
424  if ( argc > 1 && std::strcmp( argv[1], "-cvs" ) == 0 )
425  {
426    cvs = true;
427    --argc; ++argv;
428  }
429
430  if ( argc > 1 && *argv[1] == '-' )
431  {
432    license_ck = false;
433    copyright_ck = false;
434    crlf_ck = false;
435    link_ck = false;
436    long_name_ck = false;
437    tab_ck = false;
438    minmax_ck = false;
439  }
440
441  for(; argc > 1; --argc, ++argv )
442  {
443    if ( std::strcmp( argv[1], "-license" ) == 0 )
444      license_ck = true;
445    else if ( std::strcmp( argv[1], "-copyright" ) == 0 )
446      copyright_ck = true;
447    else if ( std::strcmp( argv[1], "-crlf" ) == 0 )
448        crlf_ck = true;
449    else if ( std::strcmp( argv[1], "-link" ) == 0 )
450      link_ck = true;
451    else if ( std::strcmp( argv[1], "-long_name" ) == 0 )
452      long_name_ck = true;
453    else if ( std::strcmp( argv[1], "-tab" ) == 0 )
454      tab_ck = true;
455    else if ( std::strcmp( argv[1], "-minmax" ) == 0 )
456        minmax_ck = true;
457    else
458    {
459      std::cerr << "unknown option: " << argv[1]
460      << "\nvalid options are:\n"
461      << options();
462      return 1;
463    }
464  }
465
466  inspector_list inspectors;
467
468  if ( license_ck )
469    inspectors.push_back( inspector_element( new boost::inspect::license_check ) );
470  if ( copyright_ck )
471    inspectors.push_back( inspector_element( new boost::inspect::copyright_check ) );
472  if ( crlf_ck )
473    inspectors.push_back( inspector_element( new boost::inspect::crlf_check ) );
474  if ( link_ck )
475    inspectors.push_back( inspector_element( new boost::inspect::link_check ) );
476  if ( long_name_ck )
477    inspectors.push_back( inspector_element( new boost::inspect::long_name_check ) );
478  if ( tab_ck )
479      inspectors.push_back( inspector_element( new boost::inspect::tab_check ) );
480  if ( minmax_ck )
481      inspectors.push_back( inspector_element( new boost::inspect::minmax_check ) );
482
483  // perform the actual inspection, using the requested type of iteration
484  if ( cvs )
485    visit_all<hack::cvs_iterator>( "boost-root",
486      fs::initial_path(), inspectors );
487  else
488    visit_all<fs::directory_iterator>( "boost-root",
489      fs::initial_path(), inspectors );
490
491  // close
492  for ( inspector_list::iterator itr = inspectors.begin();
493        itr != inspectors.end(); ++itr )
494  {
495    itr->inspector->close();
496  }
497
498  char run_date[128];
499  std::time_t tod;
500  std::time( &tod );
501  std::strftime( run_date, sizeof(run_date),
502    "%X UTC, %A %d %B %Y", std::gmtime( &tod ) );
503
504  std::cout << "<html>\n"
505          "<head>\n"
506          "<title>Boost Inspection Report</title>\n"
507          "</head>\n"
508          "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
509          "<table border=\"0\">\n"
510          "<tr>\n"
511          "<td><img border=\"0\" src=\"../boost.png\" width=\"277\" "
512          "height=\"86\"></td>\n"
513          "<td align=\"center\">\n"
514          "<h1>Boost Inspection Report</h1>\n"
515          "<b>Run Date:</b> " << run_date  << "\n"
516          "</td>\n"
517          "</table>\n"
518          "<p>An <a href=\"http://www.boost.org/tools/inspect/index.html\">inspection\n" 
519          "program</a> checks each file in the current Boost CVS for various problems,\n" 
520          "generating this web page as output. Problems detected include tabs in files,\n" 
521          "missing copyrights, broken URL's, and similar misdemeanors.</p>\n"
522          ;
523
524  std::cout << "<h2>Totals</h2>\n<pre>"
525            << file_count << " files scanned\n"
526            << directory_count << " directories scanned\n"
527            << error_count << " problems reported\n";
528
529  std::cout << "\nproblem counts:\n";
530
531  for ( inspector_list::iterator itr = inspectors.begin();
532        itr != inspectors.end(); ++itr )
533  {
534    itr->inspector.reset();
535  }
536
537  std::sort( msgs.begin(), msgs.end() );
538
539  if ( !msgs.empty() )
540  {
541    display_summary();
542    display_details();
543  }
544
545  std::cout << "</body>\n"
546               "</html>\n";
547  return 0;
548}
Note: See TracBrowser for help on using the repository browser.