aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <0xdec05eba@gmail.com>2018-09-20 14:55:58 +0200
committerdec05eba <0xdec05eba@gmail.com>2018-09-20 14:56:00 +0200
commitefd1bdf5576ddcff21fecc0ff5efa4d53aa8d08d (patch)
tree66a3b4df93927cf89648a5534e4b0429b355d812
parent64104c32c09d56a3a60aed2ac9096f0985f15e15 (diff)
Add raw arg type, validate names
-rw-r--r--include/ninja/Ninja.hpp14
-rw-r--r--src/Ninja.cpp81
-rw-r--r--tests/main.cpp2
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<NinjaArg> &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<ninja::NinjaArgValue> &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",