diff --git a/src/host/path_isabsolute.c b/src/host/path_isabsolute.c index 85ba254e..19731709 100644 --- a/src/host/path_isabsolute.c +++ b/src/host/path_isabsolute.c @@ -17,13 +17,59 @@ int path_isabsolute(lua_State* L) int do_isabsolute(const char* path) { - return ( - path[0] == '/' || - path[0] == '\\' || - path[0] == '$' || - path[0] == '%' || - (path[0] == '"' && path[1] == '$') || - (path[0] == '"' && path[1] == '%') || - (path[0] != '\0' && path[1] == ':') - ); + char c; + char* closing; + + if (path[0] == '/' || path[0] == '\\') + return 1; + if (isalpha(path[0]) && path[1] == ':') + return 1; + if (path[0] == '"') + return do_isabsolute(path + 1); + + // $(foo) + if (path[0] == '$' && path[1] == '(') + { + path += 2; + closing = strchr(path, ')'); + if (closing == NULL) + return 0; + + // only alpha, digits and _ allowed inside $() + while (path < closing) { + c = *path++; + if (!isalpha(c) && !isdigit(c) && c != '_') + return 0; + } + + return 1; + } + + // $ORIGIN. + if (path[0] == '$') + return 1; + + // %foo% + if (path[0] == '%') + { + // find the second closing % + path += 1; + closing = strchr(path, '%'); + if (closing == NULL) + return 0; + + // need at least one character between the %% + if (path == closing) + return 0; + + // only alpha, digits and _ allowed inside %..% + while (path < closing) { + c = *path++; + if (!isalpha(c) && !isdigit(c) && c != '_') + return 0; + } + return 1; + } + + return 0; } diff --git a/tests/base/test_path.lua b/tests/base/test_path.lua index 182c2f14..548bcebb 100755 --- a/tests/base/test_path.lua +++ b/tests/base/test_path.lua @@ -238,10 +238,30 @@ test.isfalse(path.isabsolute("a/b/c")) end - function suite.isabsolute_ReturnsTrue_OnDollarSign() + function suite.isabsolute_ReturnsTrue_OnDollarToken() test.istrue(path.isabsolute("$(SDK_HOME)/include")) end + function suite.isabsolute_ReturnsTrue_OnJustADollarSign() + test.istrue(path.isabsolute("$foo/include")) + end + + function suite.isabsolute_ReturnsFalse_OnIncompleteDollarToken() + test.isfalse(path.isabsolute("$(foo/include")) + end + + function suite.isabsolute_ReturnsTrue_OnEnvVar() + test.istrue(path.isabsolute("%FOO%/include")) + end + + function suite.isabsolute_ReturnsFalse_OnEmptyEnvVar() + test.isfalse(path.isabsolute("%%/include")) + end + + function suite.isabsolute_ReturnsFalse_OnToken() + test.isfalse(path.isabsolute("%{foo}/include")) + end + -- -- path.join() tests @@ -339,6 +359,21 @@ test.isequal("p1/./../p2", path.join("p1/.", "../p2")) end + function suite.join_absolute_second_part() + test.isequal("$ORIGIN", path.join("foo/bar", "$ORIGIN")) + end + + function suite.join_absolute_second_part1() + test.isequal("$(FOO)/bar", path.join("foo/bar", "$(FOO)/bar")) + end + + function suite.join_absolute_second_part2() + test.isequal("%ROOT%/foo", path.join("foo/bar", "%ROOT%/foo")) + end + + function suite.join_token_in_second_part() + test.isequal("foo/bar/%{test}/foo", path.join("foo/bar", "%{test}/foo")) + end -- -- path.rebase() tests