From d45e007aa8aee275904015bee5c114e95209a6db Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 24 Sep 2018 15:19:56 +0200 Subject: Escape input arg, which usually is a filename --- include/ninja/Ninja.hpp | 5 ++++- src/Ninja.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++--- tests/main.cpp | 2 +- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/include/ninja/Ninja.hpp b/include/ninja/Ninja.hpp index d0e3d50..3fed138 100644 --- a/include/ninja/Ninja.hpp +++ b/include/ninja/Ninja.hpp @@ -77,10 +77,12 @@ namespace ninja public: NinjaRule(NinjaBuildFile *buildFile, const std::string &name, const std::string &command); NinjaBuild* build(const std::string &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds = {}); + NinjaBuild* build(const std::vector &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds = {}); const std::string name; const std::string command; std::string depFile; + std::string deps; private: NinjaBuildFile *buildFile; }; @@ -88,7 +90,7 @@ namespace ninja struct NinjaBuild { const NinjaRule *rule; - const std::string in; + const std::vector in; const std::string out; const std::vector additionalArgs; const std::vector dependsOnBuilds; @@ -103,6 +105,7 @@ namespace ninja void defineGlobalVariable(const std::string &name, const std::string &value); NinjaRule* createRule(const std::string &name, const std::vector &commandArgs); NinjaBuild* build(const NinjaRule *rule, const std::string &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds = {}); + NinjaBuild* build(const NinjaRule *rule, const std::vector &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds = {}); std::string generate() const; private: diff --git a/src/Ninja.cpp b/src/Ninja.cpp index 9b9e177..778e701 100644 --- a/src/Ninja.cpp +++ b/src/Ninja.cpp @@ -72,6 +72,32 @@ namespace ninja return true; } + static std::string escape(const std::string &str) + { + std::string result; + result.reserve(str.size()); + for(char c : str) + { + if(c == '"') + result += "\\\""; + else + result += c; + } + return '"' + result + '"'; + } + + static std::string combine_escape(const std::vector &strs) + { + std::string result; + for(const std::string &str : strs) + { + if(!result.empty()) + result += ' '; + result += escape(str); + } + return result; + } + NinjaVariable::NinjaVariable(const std::string &_name) : name(_name) { @@ -93,6 +119,11 @@ namespace ninja { delete rule.second; } + + for(NinjaBuild *build : builds) + { + delete build; + } } NinjaBuild* NinjaRule::build(const std::string &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds) @@ -100,6 +131,11 @@ namespace ninja return buildFile->build(this, in, out, additionalArgs, dependsOnBuilds); } + NinjaBuild* NinjaRule::build(const std::vector &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds) + { + return buildFile->build(this, in, out, additionalArgs, dependsOnBuilds); + } + void NinjaBuildFile::defineGlobalVariable(const std::string &name, const std::string &value) { if(!isValidName(name)) @@ -127,7 +163,14 @@ namespace ninja NinjaBuild* NinjaBuildFile::build(const NinjaRule *rule, const std::string &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds) { - NinjaBuild *build = new NinjaBuild { rule, in, out, additionalArgs, dependsOnBuilds }; + NinjaBuild *build = new NinjaBuild { rule, { in }, escape(out), additionalArgs, dependsOnBuilds }; + builds.push_back(build); + return build; + } + + NinjaBuild* NinjaBuildFile::build(const NinjaRule *rule, const std::vector &in, const std::string &out, const std::vector &additionalArgs, const std::vector &dependsOnBuilds) + { + NinjaBuild *build = new NinjaBuild { rule, in, escape(out), additionalArgs, dependsOnBuilds }; builds.push_back(build); return build; } @@ -157,10 +200,14 @@ namespace ninja result += "\n depfile = "; result += rule.second->depFile; } + if(!rule.second->deps.empty()) + { + result += "\n deps = "; + result += rule.second->deps; + } result += "\n\n"; } - // TODO: enclose all names with quotes to escape whitespace? for(const NinjaBuild *build : builds) { result += "build "; @@ -168,7 +215,7 @@ namespace ninja result += ": "; result += build->rule->name; result += ' '; - result += build->in; + result += combine_escape(build->in); if(!build->dependsOnBuilds.empty()) { diff --git a/tests/main.cpp b/tests/main.cpp index f0a9b5c..e89eb19 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -25,7 +25,7 @@ int main(int argc, char **argv) NinjaArgValue argsValue = { argsVar, "$globalIncDir -std=c++14 -pedantic -fpie -MMD -MP '-Itest@exe' '-I..' -Wall -Wextra -Werror=return-type -fdiagnostics-show-option '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Winvalid-pch' -fstack-protector '-Og' -fexceptions -Wnon-virtual-dtor -g3 -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -fasynchronous-unwind-tables" }; - compileCppRule->build("../../main.cpp", "test@exe/main.cpp.o", { argsValue }); + compileCppRule->build("../../ma in\".cpp", "test@exe/main.cpp.o", { argsValue }); NinjaArgValue linkArgsValue = { linkArgsVar, "-Wl,--no-undefined,--as-needed -ldl -lm -pthread -pthread \"/home/dec05eba/git/libninja/sibs-build/debug/liblibninja.so\"" }; buildExeRule->build("test@exe/main.cpp.o", "test", { argsValue }); -- cgit v1.2.3