Skip to content

Commit

Permalink
Fix simple explicit filenames.
Browse files Browse the repository at this point in the history
  • Loading branch information
dillof committed Apr 13, 2024
1 parent 00942c7 commit db41faa
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/FilenameList.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ FilenameList::FilenameList(Tokenizer& tokenizer, Type type) {
force_build = (type == Type::BUILD);

while (true) {
auto word = FilenameWord{tokenizer};
auto word = FilenameWord{tokenizer, force_build};
if (!word.empty()) {
words.emplace_back(word);
}
Expand Down
83 changes: 50 additions & 33 deletions src/FilenameWord.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "FilenameVariable.h"

FilenameWord::FilenameWord(Tokenizer& tokenizer) {
FilenameWord::FilenameWord(Tokenizer& tokenizer, bool force_build): force_build{force_build} {
std::string string;

auto first = true;
Expand Down Expand Up @@ -97,58 +97,75 @@ FilenameWord::FilenameWord(Tokenizer& tokenizer) {
}

void FilenameWord::resolve(const ResolveContext& context) {
auto contains_filename_variable = false;
for (auto& element : elements) {
if (std::holds_alternative<VariableReference>(element)) {
auto& variable_reference = std::get<VariableReference>(element);
variable_reference.resolve(context);
if (variable_reference.is_text_variable()) {
element = variable_reference.variable->string();
}
else {
contains_filename_variable = true;
}
}
}
if (!contains_filename_variable) {
auto name = std::string();
for (const auto& element: elements) {
name += std::get<std::string>(element);
}
filename = Filename{force_build ? Filename::Type::BUILD : Filename::Type::UNKNOWN, name};
filename->resolve(context);
}
}

void FilenameWord::collect_filenames(std::vector<Filename>& filenames) const {
std::string prefix;
std::string postfix;
auto current_string = &prefix;
const FilenameVariable* filename_variable{};

for (auto& element: elements) {
if (std::holds_alternative<std::string>(element)) {
*current_string += std::get<std::string>(element);
}
else {
auto variable = std::get<VariableReference>(element);
if (variable.is_filename_variable()) {
if (filename_variable) {
throw Exception("multiple filename variables in filename not allowed");
if (filename) {
filenames.emplace_back(*filename);
}
else {
std::string prefix;
std::string postfix;
auto current_string = &prefix;
const FilenameVariable* filename_variable{};

for (auto& element : elements) {
if (std::holds_alternative<std::string>(element)) {
*current_string += std::get<std::string>(element);
}
else {
auto variable = std::get<VariableReference>(element);
if (variable.is_filename_variable()) {
if (filename_variable) {
throw Exception("multiple filename variables in filename not allowed");
}
else {
filename_variable = variable.variable->as_filename();
current_string = &postfix;
}
}
else {
filename_variable = variable.variable->as_filename();
current_string = &postfix;
*current_string += variable.variable->string();
}
}
else {
*current_string += variable.variable->string();
}
}
}

if (filename_variable) {
if (prefix.empty() && postfix.empty()) {
filename_variable->collect_filenames(filenames);
if (filename_variable) {
if (prefix.empty() && postfix.empty()) {
filename_variable->collect_filenames(filenames);
}
else {
std::vector<Filename> inner_filenames;
filename_variable->collect_filenames(inner_filenames);
for (auto& filename : inner_filenames) {
filename.name = prefix + filename.name + postfix;
}
filenames.insert(filenames.end(), inner_filenames.begin(), inner_filenames.end());
}
}
else {
std::vector<Filename> inner_filenames;
filename_variable->collect_filenames(inner_filenames);
for (auto& filename : inner_filenames) {
filename.name = prefix + filename.name + postfix;
}
filenames.insert(filenames.end(), inner_filenames.begin(), inner_filenames.end());
filenames.emplace_back(prefix);
}
}
else {
filenames.emplace_back(prefix);
}
}
4 changes: 3 additions & 1 deletion src/FilenameWord.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class FilenameList;

class FilenameWord {
public:
explicit FilenameWord(Tokenizer& tokenizer);
explicit FilenameWord(Tokenizer& tokenizer, bool force_build = false);
explicit FilenameWord(std::string word): elements{std::move(word)} {}

[[nodiscard]] bool empty() const {return elements.empty();}
Expand All @@ -50,6 +50,8 @@ class FilenameWord {

private:
std::vector<std::variant<std::string, VariableReference>> elements;
std::optional<Filename> filename;
bool force_build{false};
};

#endif // EXPLICITFILENAME_H
4 changes: 2 additions & 2 deletions src/Text.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ void Text::resolve(const ResolveContext& context) {
std::string Text::string() const {
auto result = std::string{};

for (auto& element : words) {
result += element.string();
for (auto& word : words) {
result += word.string();
}

return result;
Expand Down
27 changes: 27 additions & 0 deletions tests/explicit-filename.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
arguments ..
file input <>
input
end-of-inline-data
file build.fninja <>
rule a
command = {{input}} $in $out
flags = --verbose

build output: a input
end-of-inline-data
file build/build.ninja {} <>
# This file is automatically created by fast-ninja from ../build.fninja
# Do not edit.

rule a
command = ../input $in $out
flags = --verbose

rule fast-ninja
command = fast-ninja ..
generator = 1

build output : a ../input

build build.ninja : fast-ninja ../build.fninja
end-of-inline-data

0 comments on commit db41faa

Please sign in to comment.