Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/bcp/scan_licence.cpp @ 12

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

added boost

File size: 8.8 KB
Line 
1/*
2 *
3 * Copyright (c) 2003 Dr John Maddock
4 * Use, modification and distribution is subject to the
5 * Boost Software License, Version 1.0. (See accompanying file
6 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 *
8 */
9
10#include "licence_info.hpp"
11#include "bcp_imp.hpp"
12#include "fileview.hpp"
13#include <fstream>
14#include <iostream>
15
16
17const int boost_license_lines = 3;
18static const std::string boost_license_text[boost_license_lines] = {
19  "Distributed under the Boost Software License, Version 1.0. (See",
20  "accompanying file LICENSE_1_0.txt or copy at",
21  "http://www.boost.org/LICENSE_1_0.txt)"
22};
23
24fileview::const_iterator
25context_before_license(const fileview& v, fileview::const_iterator start,
26                       int context_lines = 3)
27{
28  char last_char = '\0';
29  while (start != v.begin() && context_lines >= 0) {
30    if (*start == '\r' || *start == '\n'
31        && (last_char == *start || (last_char != '\r' && last_char != '\n')))
32        --context_lines;
33
34    last_char = *start;
35    --start;
36  }
37
38  // Unless we hit the beginning, we need to step forward one to start
39  // on the next line.
40  if (start != v.begin()) ++start;
41
42  return start;
43}
44
45fileview::const_iterator
46context_after_license(const fileview& v, fileview::const_iterator end,
47                      int context_lines = 3)
48{
49  char last_char = '\0';
50  while (end != v.end() && context_lines >= 0) {
51    if (*end == '\r' || *end == '\n'
52        && (last_char == *end || (last_char != '\r' && last_char != '\n')))
53        --context_lines;
54
55    last_char = *end;
56    ++end;
57  }
58
59  return end;
60}
61
62static std::string
63find_prefix(const fileview& v, fileview::const_iterator start_of_line)
64{
65  while (start_of_line != v.begin()
66         && *start_of_line != '\n'
67         && *start_of_line != '\r')
68    --start_of_line;
69  if (start_of_line != v.begin())
70    ++start_of_line;
71
72  fileview::const_iterator first_noncomment_char = start_of_line;
73  while (*first_noncomment_char == '/'
74         || *first_noncomment_char == '*'
75         || *first_noncomment_char == ' '
76         || *first_noncomment_char == '#')
77    ++first_noncomment_char;
78
79  return std::string(start_of_line, first_noncomment_char);
80}
81
82static std::string
83html_escape(fileview::const_iterator first, fileview::const_iterator last)
84{
85  std::string result;
86  while (first != last) {
87    switch (*first) {
88    case '<': result += "&lt;"; break;
89    case '>': result += "&gt;"; break;
90    case '&': result += "&amp;"; break;
91    default: result += *first;
92    }
93    ++first;
94  }
95  return result;
96}
97
98static bool is_non_bsl_license(int index)
99{
100  return index > 2;
101}
102
103void bcp_implementation::scan_license(const fs::path& p, const fileview& v)
104{
105   std::pair<const license_info*, int> licenses = get_licenses();
106   //
107   // scan file for all the licenses in the list:
108   //
109   int license_count = 0;
110   int author_count = 0;
111   int nonbsl_author_count = 0;
112   bool has_non_bsl_license = false;
113   fileview::const_iterator start_of_license = v.begin(), 
114                            end_of_license = v.end();
115   bool start_in_middle_of_line = false;
116
117   for(int i = 0; i < licenses.second; ++i)
118   {
119      boost::match_results<fileview::const_iterator> m;
120      if(boost::regex_search(v.begin(), v.end(), m, licenses.first[i].license_signature))
121      {
122           start_of_license = m[0].first;
123         end_of_license = m[0].second;
124
125         if (is_non_bsl_license(i) && i < licenses.second - 1) 
126           has_non_bsl_license = true;
127
128         // add this license to the list:
129         m_license_data[i].files.insert(p);
130         ++license_count;
131         //
132         // scan for the associated copyright declarations:
133         //
134         boost::regex_iterator<const char*> cpy(v.begin(), v.end(), licenses.first[i].copyright_signature);
135         boost::regex_iterator<const char*> ecpy;
136         while(cpy != ecpy)
137         {
138#if 0
139             // Not dealing with copyrights because we don't have the years
140            if ((*cpy)[0].first < start_of_license)
141              start_of_license = (*cpy)[0].first;
142            if ((*cpy)[0].second > end_of_license)
143              end_of_license = (*cpy)[0].second;
144#endif
145
146            // extract the copy holders as a list:
147            std::string author_list = cpy->format(licenses.first[i].copyright_formatter, boost::format_all);
148            // now enumerate that list for all the names:
149            static const boost::regex author_separator("(?:\\s*,(?!\\s*(?:inc|ltd)\\b)\\s*|\\s+(,\\s*)?(and|&)\\s+)|by\\s+", boost::regex::perl | boost::regex::icase);
150            boost::regex_token_iterator<std::string::const_iterator> atr(author_list.begin(), author_list.end(), author_separator, -1);
151            boost::regex_token_iterator<std::string::const_iterator> eatr;
152            while(atr != eatr)
153            {
154               // get the reformatted authors name:
155               std::string name = format_authors_name(*atr);
156               // add to list of authors for this file:
157               if(name.size() && name[0] != '-')
158               {
159                  m_license_data[i].authors.insert(name);
160                  // add file to author index:
161                  m_author_data[name].insert(p);
162                  ++author_count;
163
164                  // If this is not the Boost Software License (license 0), and the author hasn't given
165                  // blanket permission, note this for the report.
166                  if (has_non_bsl_license
167                      && m_bsl_authors.find(name) == m_bsl_authors.end()) {
168                    ++nonbsl_author_count;
169                    m_authors_for_bsl_migration.insert(name);
170                  }
171               }
172               ++atr;
173            }
174            ++cpy;
175         }
176
177         while (start_of_license != v.begin()
178                && *start_of_license != '\r'
179                && *start_of_license != '\n'
180                && *start_of_license != '.')
181           --start_of_license;
182
183         if (start_of_license != v.begin()) {
184           if (*start_of_license == '.')
185             start_in_middle_of_line = true;
186           ++start_of_license;
187         }
188
189         while (end_of_license != v.end()
190                && *end_of_license != '\r'
191                && *end_of_license != '\n')
192           ++end_of_license;
193      }
194   }
195   if(license_count == 0)
196      m_unknown_licenses.insert(p);
197   if(license_count && !author_count)
198      m_unknown_authors.insert(p);
199
200   if (has_non_bsl_license) {
201     bool converted = false;
202     if (nonbsl_author_count == 0 
203         && license_count == 1) {
204       // Grab a few lines of context
205       fileview::const_iterator context_start = 
206         context_before_license(v, start_of_license);
207       fileview::const_iterator context_end = 
208         context_after_license(v, end_of_license);
209
210       // TBD: For files that aren't C++ code, this will have to
211       // change.
212       std::string prefix = find_prefix(v, start_of_license);
213
214       // Create enough information to permit manual verification of
215       // the correctness of the transformation
216       std::string before_conversion = 
217         html_escape(context_start, start_of_license);
218       before_conversion += "<b>";
219       before_conversion += html_escape(start_of_license, end_of_license);
220       before_conversion += "</b>";
221       before_conversion += html_escape(end_of_license, context_end);
222
223       std::string after_conversion = 
224         html_escape(context_start, start_of_license);
225       if (start_in_middle_of_line)
226         after_conversion += '\n';
227
228       after_conversion += "<b>";
229       for (int i = 0; i < boost_license_lines; ++i) {
230         if (i > 0) after_conversion += '\n';
231         after_conversion += prefix + boost_license_text[i];
232       }
233       after_conversion += "</b>";
234       after_conversion += html_escape(end_of_license, context_end);
235
236       m_converted_to_bsl[p] = 
237         std::make_pair(before_conversion, after_conversion);
238
239       // Perform the actual conversion
240       if (m_bsl_convert_mode) {
241          try{
242            std::ofstream out((m_boost_path / p).native_file_string().c_str());
243            if (!out) {
244               std::string msg("Cannot open file for license conversion: ");
245               msg += p.native_file_string();
246               std::runtime_error e(msg);
247               boost::throw_exception(e);
248            }
249
250            out << std::string(v.begin(), start_of_license);
251            if (start_in_middle_of_line)
252               out << std::endl;
253
254            for (int j = 0; j < boost_license_lines; ++j) {
255               if (j > 0) out << std::endl;
256               out << prefix << boost_license_text[j];
257            }
258            out << std::string(end_of_license, v.end());
259
260            converted = true;
261       }
262       catch(const std::exception& e)
263       {
264          std::cerr << e.what() << std::endl;
265       }
266      }
267     }
268
269     if (!converted) {
270       if (nonbsl_author_count > 0) m_cannot_migrate_to_bsl.insert(p);
271       else m_can_migrate_to_bsl.insert(p);
272     }
273   }
274}
275
Note: See TracBrowser for help on using the repository browser.