| /* |
| * |
| * Copyright (c) 2003 Dr John Maddock |
| * Use, modification and distribution is subject to the |
| * Boost Software License, Version 1.0. (See accompanying file |
| * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| * |
| */ |
| |
| #include "licence_info.hpp" |
| #include "bcp_imp.hpp" |
| #include "fileview.hpp" |
| #include <fstream> |
| #include <iostream> |
| |
| |
| const int boost_license_lines = 3; |
| static const std::string boost_license_text[boost_license_lines] = { |
| "Distributed under the Boost Software License, Version 1.0. (See", |
| "accompanying file LICENSE_1_0.txt or copy at", |
| "http://www.boost.org/LICENSE_1_0.txt)" |
| }; |
| |
| fileview::const_iterator |
| context_before_license(const fileview& v, fileview::const_iterator start, |
| int context_lines = 3) |
| { |
| char last_char = '\0'; |
| while (start != v.begin() && context_lines >= 0) { |
| if (*start == '\r' || *start == '\n' |
| && (last_char == *start || (last_char != '\r' && last_char != '\n'))) |
| --context_lines; |
| |
| last_char = *start; |
| --start; |
| } |
| |
| // Unless we hit the beginning, we need to step forward one to start |
| // on the next line. |
| if (start != v.begin()) ++start; |
| |
| return start; |
| } |
| |
| fileview::const_iterator |
| context_after_license(const fileview& v, fileview::const_iterator end, |
| int context_lines = 3) |
| { |
| char last_char = '\0'; |
| while (end != v.end() && context_lines >= 0) { |
| if (*end == '\r' || *end == '\n' |
| && (last_char == *end || (last_char != '\r' && last_char != '\n'))) |
| --context_lines; |
| |
| last_char = *end; |
| ++end; |
| } |
| |
| return end; |
| } |
| |
| static std::string |
| find_prefix(const fileview& v, fileview::const_iterator start_of_line) |
| { |
| while (start_of_line != v.begin() |
| && *start_of_line != '\n' |
| && *start_of_line != '\r') |
| --start_of_line; |
| if (start_of_line != v.begin()) |
| ++start_of_line; |
| |
| fileview::const_iterator first_noncomment_char = start_of_line; |
| while (*first_noncomment_char == '/' |
| || *first_noncomment_char == '*' |
| || *first_noncomment_char == ' ' |
| || *first_noncomment_char == '#') |
| ++first_noncomment_char; |
| |
| return std::string(start_of_line, first_noncomment_char); |
| } |
| |
| static std::string |
| html_escape(fileview::const_iterator first, fileview::const_iterator last) |
| { |
| std::string result; |
| while (first != last) { |
| switch (*first) { |
| case '<': result += "<"; break; |
| case '>': result += ">"; break; |
| case '&': result += "&"; break; |
| default: result += *first; |
| } |
| ++first; |
| } |
| return result; |
| } |
| |
| static bool is_non_bsl_license(int index) |
| { |
| return index > 2; |
| } |
| |
| void bcp_implementation::scan_license(const fs::path& p, const fileview& v) |
| { |
| std::pair<const license_info*, int> licenses = get_licenses(); |
| // |
| // scan file for all the licenses in the list: |
| // |
| int license_count = 0; |
| int author_count = 0; |
| int nonbsl_author_count = 0; |
| bool has_non_bsl_license = false; |
| fileview::const_iterator start_of_license = v.begin(), |
| end_of_license = v.end(); |
| bool start_in_middle_of_line = false; |
| |
| for(int i = 0; i < licenses.second; ++i) |
| { |
| boost::match_results<fileview::const_iterator> m; |
| if(boost::regex_search(v.begin(), v.end(), m, licenses.first[i].license_signature)) |
| { |
| start_of_license = m[0].first; |
| end_of_license = m[0].second; |
| |
| if (is_non_bsl_license(i) && i < licenses.second - 1) |
| has_non_bsl_license = true; |
| |
| // add this license to the list: |
| m_license_data[i].files.insert(p); |
| ++license_count; |
| // |
| // scan for the associated copyright declarations: |
| // |
| boost::regex_iterator<const char*> cpy(v.begin(), v.end(), licenses.first[i].copyright_signature); |
| boost::regex_iterator<const char*> ecpy; |
| while(cpy != ecpy) |
| { |
| #if 0 |
| // Not dealing with copyrights because we don't have the years |
| if ((*cpy)[0].first < start_of_license) |
| start_of_license = (*cpy)[0].first; |
| if ((*cpy)[0].second > end_of_license) |
| end_of_license = (*cpy)[0].second; |
| #endif |
| |
| // extract the copy holders as a list: |
| std::string author_list = cpy->format(licenses.first[i].copyright_formatter, boost::format_all); |
| // now enumerate that list for all the names: |
| static const boost::regex author_separator("(?:\\s*,(?!\\s*(?:inc|ltd)\\b)\\s*|\\s+(,\\s*)?(and|&)\\s+)|by\\s+", boost::regex::perl | boost::regex::icase); |
| boost::regex_token_iterator<std::string::const_iterator> atr(author_list.begin(), author_list.end(), author_separator, -1); |
| boost::regex_token_iterator<std::string::const_iterator> eatr; |
| while(atr != eatr) |
| { |
| // get the reformatted authors name: |
| std::string name = format_authors_name(*atr); |
| // add to list of authors for this file: |
| if(name.size() && name[0] != '-') |
| { |
| m_license_data[i].authors.insert(name); |
| // add file to author index: |
| m_author_data[name].insert(p); |
| ++author_count; |
| |
| // If this is not the Boost Software License (license 0), and the author hasn't given |
| // blanket permission, note this for the report. |
| if (has_non_bsl_license |
| && m_bsl_authors.find(name) == m_bsl_authors.end()) { |
| ++nonbsl_author_count; |
| m_authors_for_bsl_migration.insert(name); |
| } |
| } |
| ++atr; |
| } |
| ++cpy; |
| } |
| |
| while (start_of_license != v.begin() |
| && *start_of_license != '\r' |
| && *start_of_license != '\n' |
| && *start_of_license != '.') |
| --start_of_license; |
| |
| if (start_of_license != v.begin()) { |
| if (*start_of_license == '.') |
| start_in_middle_of_line = true; |
| ++start_of_license; |
| } |
| |
| while (end_of_license != v.end() |
| && *end_of_license != '\r' |
| && *end_of_license != '\n') |
| ++end_of_license; |
| } |
| } |
| if(license_count == 0) |
| m_unknown_licenses.insert(p); |
| if(license_count && !author_count) |
| m_unknown_authors.insert(p); |
| |
| if (has_non_bsl_license) { |
| bool converted = false; |
| if (nonbsl_author_count == 0 |
| && license_count == 1) { |
| // Grab a few lines of context |
| fileview::const_iterator context_start = |
| context_before_license(v, start_of_license); |
| fileview::const_iterator context_end = |
| context_after_license(v, end_of_license); |
| |
| // TBD: For files that aren't C++ code, this will have to |
| // change. |
| std::string prefix = find_prefix(v, start_of_license); |
| |
| // Create enough information to permit manual verification of |
| // the correctness of the transformation |
| std::string before_conversion = |
| html_escape(context_start, start_of_license); |
| before_conversion += "<b>"; |
| before_conversion += html_escape(start_of_license, end_of_license); |
| before_conversion += "</b>"; |
| before_conversion += html_escape(end_of_license, context_end); |
| |
| std::string after_conversion = |
| html_escape(context_start, start_of_license); |
| if (start_in_middle_of_line) |
| after_conversion += '\n'; |
| |
| after_conversion += "<b>"; |
| for (int i = 0; i < boost_license_lines; ++i) { |
| if (i > 0) after_conversion += '\n'; |
| after_conversion += prefix + boost_license_text[i]; |
| } |
| after_conversion += "</b>"; |
| after_conversion += html_escape(end_of_license, context_end); |
| |
| m_converted_to_bsl[p] = |
| std::make_pair(before_conversion, after_conversion); |
| |
| // Perform the actual conversion |
| if (m_bsl_convert_mode) { |
| try{ |
| std::ofstream out((m_boost_path / p).native_file_string().c_str()); |
| if (!out) { |
| std::string msg("Cannot open file for license conversion: "); |
| msg += p.native_file_string(); |
| std::runtime_error e(msg); |
| boost::throw_exception(e); |
| } |
| |
| out << std::string(v.begin(), start_of_license); |
| if (start_in_middle_of_line) |
| out << std::endl; |
| |
| for (int j = 0; j < boost_license_lines; ++j) { |
| if (j > 0) out << std::endl; |
| out << prefix << boost_license_text[j]; |
| } |
| out << std::string(end_of_license, v.end()); |
| |
| converted = true; |
| } |
| catch(const std::exception& e) |
| { |
| std::cerr << e.what() << std::endl; |
| } |
| } |
| } |
| |
| if (!converted) { |
| if (nonbsl_author_count > 0) m_cannot_migrate_to_bsl.insert(p); |
| else m_can_migrate_to_bsl.insert(p); |
| } |
| } |
| } |
| |