From efd1bdf5576ddcff21fecc0ff5efa4d53aa8d08d Mon Sep 17 00:00:00 2001 From: dec05eba <0xdec05eba@gmail.com> Date: Thu, 20 Sep 2018 14:55:58 +0200 Subject: Add raw arg type, validate names --- include/ninja/Ninja.hpp | 14 +++++++-- src/Ninja.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++------ tests/main.cpp | 2 +- 3 files changed, 84 insertions(+), 13 deletions(-) diff --git a/include/ninja/Ninja.hpp b/include/ninja/Ninja.hpp index cd9be0a..e2b4ab5 100644 --- a/include/ninja/Ninja.hpp +++ b/include/ninja/Ninja.hpp @@ -12,7 +12,7 @@ namespace ninja NONE, VARIABLE_ALREADY_DEFINED, RULE_ALREADY_DEFINED, - RULE_AREADY_BUILT + INVALID_NAME }; class NinjaException : public std::runtime_error @@ -30,6 +30,7 @@ namespace ninja struct NinjaVariable { + NinjaVariable(const std::string &name); const std::string name; }; @@ -42,13 +43,22 @@ namespace ninja { NONE, VALUE, - VARIABLE + VARIABLE, + RAW }; NinjaArg() : type(Type::NONE) {} NinjaArg(const std::string &value) : type(Type::VALUE), arg(value) {} NinjaArg(const NinjaVariable &var) : type(Type::VARIABLE), arg(var.name) {} + static NinjaArg createRaw(const std::string &value) + { + NinjaArg arg; + arg.type = Type::RAW; + arg.arg = value; + return arg; + } + Type type; std::string arg; }; diff --git a/src/Ninja.cpp b/src/Ninja.cpp index 7b3212e..f74ab04 100644 --- a/src/Ninja.cpp +++ b/src/Ninja.cpp @@ -10,15 +10,75 @@ namespace ninja { if(!result.empty()) result += ' '; - result += '\''; - if(arg.type == NinjaArg::Type::VARIABLE) - result += "$"; - result += arg.arg; - result += '\''; + + NinjaArg::Type argType = arg.type; + if(!arg.arg.empty() && arg.arg[0] == '$') + argType = NinjaArg::Type::RAW; + + switch(argType) + { + case NinjaArg::Type::VALUE: + { + result += '\'' + arg.arg + '\''; + break; + } + case NinjaArg::Type::VARIABLE: + { + result += '$' + arg.arg; + break; + } + case NinjaArg::Type::RAW: + { + result += arg.arg; + break; + } + } } return result; } + static bool isAlpha(char c) + { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + } + + static bool isNum(char c) + { + return c >= '0' && c <= '9'; + } + + static bool isAlnum(char c) + { + return isAlpha(c) || isNum(c); + } + + static bool isValidName(const std::string &name) + { + if(name.empty()) + return false; + + if(name.size() > 100) + return false; + + if(!isAlpha(name[0]) && name[0] != '_') + return false; + + for(int i = 1; i < name.size(); ++i) + { + if(!isAlnum(name[i]) && name[i] != '_') + return false; + } + + return true; + } + + NinjaVariable::NinjaVariable(const std::string &_name) : + name(_name) + { + if(!isValidName(name)) + throw NinjaException(NinjaError::INVALID_NAME, "Invalid variable name, has to match [a-zA-Z_]{1}[a-zA-Z0-9_]{0,98}"); + } + NinjaRule::NinjaRule(NinjaBuildFile *_buildFile, const std::string &_name, const std::string &_command) : buildFile(_buildFile), name(_name), @@ -42,6 +102,9 @@ namespace ninja void NinjaBuildFile::defineGlobalVariable(const std::string &name, const std::string &value) { + if(!isValidName(name)) + throw NinjaException(NinjaError::INVALID_NAME, "Invalid global variable name, has to match [a-zA-Z_]{1}[a-zA-Z0-9_]{0,98}"); + auto it = globalVariables.find(name); if(it != globalVariables.end()) throw NinjaException(NinjaError::VARIABLE_ALREADY_DEFINED, "Global variable already defined: " + name); @@ -50,6 +113,9 @@ namespace ninja NinjaRule* NinjaBuildFile::createRule(const std::string &name, const std::vector &commandArgs) { + if(!isValidName(name)) + throw NinjaException(NinjaError::INVALID_NAME, "Invalid rule name, has to match [a-zA-Z_]{1}[a-zA-Z0-9_]{0,98}"); + auto it = rules.find(name); if(it != rules.end()) throw NinjaException(NinjaError::RULE_ALREADY_DEFINED, "Rule already defined: " + name); @@ -61,11 +127,6 @@ namespace ninja void NinjaBuildFile::build(const NinjaRule *rule, const std::string &in, const std::string &out, const std::vector &additionalArgs) { - for(const NinjaBuild &build : builds) - { - if(build.rule == rule) - throw NinjaException(NinjaError::RULE_AREADY_BUILT, "Rule already built: " + rule->name); - } builds.push_back({ rule, in, out, additionalArgs }); } diff --git a/tests/main.cpp b/tests/main.cpp index 9af7241..f0a9b5c 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -16,7 +16,7 @@ int main(int argc, char **argv) compileCppRule->depFile = "$out.d"; NinjaRule *buildExeRule = ninjaBuildFile.createRule("BUILD_EXEC", - { NinjaArg("c++"), NinjaArg(argsVar), NinjaArg("-o"), NinjaArg("$out"), NinjaArg("$in"), NinjaArg(linkArgsVar), NinjaArg("$aliasing") }); + { NinjaArg("c++"), NinjaArg(argsVar), NinjaArg("-o"), NinjaArg("$out"), NinjaArg("$in"), NinjaArg(linkArgsVar) }); buildExeRule->depFile = "$out.d"; NinjaRule *compileCRule = ninjaBuildFile.createRule("c_COMPILER", -- cgit v1.2.3