Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions src/cmake_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "fs.hpp"
#include "project_parser.hpp"
#include <algorithm>
#include <cctype> // Wael-MA: we call isspace below, better to include it explicitly

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments need to go.

#include <cstdio>
#include <memory>
#include <sstream>
Expand Down Expand Up @@ -765,13 +766,10 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
}

auto contains_language_source = [&project_extensions](const std::vector<std::string> &sources) {
for (const auto &source : sources) {
auto extension = fs::path(source).extension().string();
if (project_extensions.count(extension) > 0) {
return true;
}
}
return false;
// Wael-MA: swapped the manual scan for std::any_of, behavior is the same
return std::any_of(sources.begin(), sources.end(), [&project_extensions](const std::string &source) {
return project_extensions.count(fs::path(source).extension().string()) > 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is any easier to read and std::any_of has horrible codegen in debug mode, don't think it's worthwhile.

});
};

Generator gen(project, path);
Expand Down Expand Up @@ -1244,12 +1242,10 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
auto has_include_after = false;
{
auto has_include = [](const parser::ConditionVector &includes) {
for (const auto &itr : includes) {
for (const auto &jtr : itr.second) {
return true;
}
}
return false;
// Wael-MA: std::any_of does the same scan, just a lot easier to read
using value_type = std::pair<std::string, std::vector<std::string>>;
return std::any_of(includes.begin(), includes.end(),
[](const value_type &itr) { return !itr.second.empty(); });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above, I don't think this makes the code any easier to read.

};
auto has_include_helper = [&](const parser::Target &target) {
if (!target.cmake_before.empty() || has_include(target.include_before)) {
Expand Down Expand Up @@ -1935,7 +1931,8 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
auto generated_cmake = ss.str();

// Make sure the file ends in a single newline
while (!generated_cmake.empty() && std::isspace(generated_cmake.back())) {
// Wael-MA: isspace must receive an unsigned char, plain chars can be negative
while (!generated_cmake.empty() && std::isspace(static_cast<unsigned char>(generated_cmake.back()))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use a C cast

generated_cmake.pop_back();
}
generated_cmake += '\n';
Expand Down
40 changes: 23 additions & 17 deletions src/project_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ static MsvcRuntimeType parse_msvcRuntimeType(const std::string &name) {
return msvc_last;
}

static std::string msvc_runtime_error(const std::string &runtime) {
// Wael-MA: one shared spot for this error text, it was copy-pasted in two places
std::string error = "Unknown runtime '" + runtime + "'\n";
error += "Available types:\n";
for (const char *type_name : msvcRuntimeTypeNames) {
error += " - ";
error += type_name;
error += '\n';
}
error.pop_back(); // Remove last newline
return error;
}

using TomlBasicValue = toml::basic_value<toml::discard_comments, tsl::ordered_map, std::vector>;

static std::string format_key_message(const std::string &message, const toml::key &ky, const TomlBasicValue &value) {
Expand Down Expand Up @@ -419,13 +432,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
if (!msvc_runtime.empty()) {
project_msvc_runtime = parse_msvcRuntimeType(msvc_runtime);
if (project_msvc_runtime == msvc_last) {
std::string error = "Unknown runtime '" + msvc_runtime + "'\n";
error += "Available types:\n";
for (std::string type_name : msvcRuntimeTypeNames) {
error += " - " + type_name + "\n";
}
error.pop_back(); // Remove last newline
throw_key_error(error, msvc_runtime, project.find("msvc-runtime"));
throw_key_error(msvc_runtime_error(msvc_runtime), msvc_runtime, project.find("msvc-runtime"));
}
}
}
Expand Down Expand Up @@ -657,7 +664,9 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p

auto is_cmake_arg = [](const std::string &s) {
for (auto c : s) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to unsigned char c : s and then you don't have to touch the code below

if (!(std::isdigit(c) || std::isupper(c) || c == '_')) {
// Wael-MA: cast to unsigned char first, <cctype> functions are UB on negative bytes
auto uc = static_cast<unsigned char>(c);
if (!(std::isdigit(uc) || std::isupper(uc) || c == '_')) {
return false;
}
}
Expand Down Expand Up @@ -695,7 +704,8 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
throw_key_error("Empty hash value", argItr.first, argItr.second);
}
for (char c : value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

if (!std::isxdigit(c)) {
// Wael-MA: isxdigit also wants an unsigned char, otherwise it's the same UB
if (!std::isxdigit(static_cast<unsigned char>(c))) {
throw_key_error("Hash value must be a hex string", argItr.first, argItr.second);
}
}
Expand Down Expand Up @@ -1098,19 +1108,13 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
target.properties[cond_itr.first]["MSVC_RUNTIME_LIBRARY"] = "MultiThreaded$<$<CONFIG:Debug>:Debug>";
break;
default: {
std::string error = "Unknown runtime '" + cond_itr.second + "'\n";
error += "Available types:\n";
for (std::string type_name : msvcRuntimeTypeNames) {
error += " - " + type_name + "\n";
}
error.pop_back(); // Remove last newline
const TomlBasicValue *report;
if (cond_itr.first.empty()) {
report = &t.find("msvc-runtime");
} else {
report = &t.find(cond_itr.first).as_table().find("msvc-runtime").value();
}
throw_key_error(error, cond_itr.second, *report);
throw_key_error(msvc_runtime_error(cond_itr.second), cond_itr.second, *report);
}
}
}
Expand Down Expand Up @@ -1308,7 +1312,9 @@ bool Project::cmake_minimum_version(int major, int minor) const {

bool Project::is_condition_name(const std::string &name) {
for (auto ch : name) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

if (!std::isalnum(ch) && ch != '-' && ch != '_') {
// Wael-MA: casting to unsigned char keeps isalnum well-defined for any input byte
auto uc = static_cast<unsigned char>(ch);
if (!std::isalnum(uc) && ch != '-' && ch != '_') {
return false;
}
}
Expand Down