diff options
Diffstat (limited to 'build/parser.cxx')
-rw-r--r-- | build/parser.cxx | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/build/parser.cxx b/build/parser.cxx index a030a09..8f4f81d 100644 --- a/build/parser.cxx +++ b/build/parser.cxx @@ -35,9 +35,9 @@ namespace build typedef token_type type; // Given a target or prerequisite name, figure out its type, taking - // into account extensions, trailing '/', or anything else that might - // be relevant. Also process the name (in place) by extracting the - // extension, adjusting dir/value, etc. + // into account extensions, special names (e.g., '.' and '..'), or + // anything else that might be relevant. Also process the name (in + // place) by extracting the extension, adjusting dir/value, etc. // const target_type& find_target_type (name& n, const location& l, const string*& ext) @@ -49,11 +49,9 @@ namespace build const char* tt; if (n.type.empty ()) { - // Empty name, '.' and '..', or a name ending with a directory - // separator signifies a directory. + // Empty name or '.' and '..' signify a directory. // - if (v.empty () || v == "." || v == ".." || - path::traits::is_separator (v.back ())) + if (v.empty () || v == "." || v == "..") tt = "dir"; else //@@ TODO: derive type from extension. @@ -189,7 +187,7 @@ namespace build location nloc (get_location (t, &path_)); names_type ns (tt != type::colon ? names (t, tt) - : names_type ({name ("")})); + : names_type ({name ("dir", path (), string ())})); if (tt == type::colon) { @@ -214,7 +212,9 @@ namespace build bool dir (false); for (const auto& n: ns) { - if (n.type.empty () && n.value.back () == '/') + // A name represents directory as an empty value. + // + if (n.type.empty () && n.value.empty ()) { if (ns.size () != 1) { @@ -233,14 +233,8 @@ namespace build { scope& prev (*scope_); - // On Win32 translate the root path to the special empty path. - // Search for root_scope for details. - // -#ifdef _WIN32 - path p (ns[0].value != "/" ? path (ns[0].value) : path ()); -#else - path p (ns[0].value); -#endif + path p (move (ns[0].dir)); // Steal. + if (p.relative ()) p = prev.path () / p; @@ -676,13 +670,15 @@ namespace build continue; } + string::size_type p (name.rfind ('/')); + string::size_type n (name.size () - 1); + // See if this is a type name, directory prefix, or both. That is, // it is followed by '{'. // if (tt == type::lcbrace) { next (t, tt); - string::size_type p (name.rfind ('/')), n (name.size () - 1); if (p != n && tp != nullptr) fail (t) << "nested type name " << name; @@ -727,9 +723,36 @@ namespace build continue; } - ns.emplace_back ((tp != nullptr ? *tp : string ()), - (dp != nullptr ? *dp : path ()), - move (name)); + // If it ends with a directory separator, then it is a directory. + // Note that at this stage we don't treat '.' and '..' as special + // (unless they are specified with a directory separator) because + // then we would have ended up treating '.: ...' as a directory + // scope. Instead, this is handled higher up, in find_target_type(). + // + // @@ TODO: and not quoted + // + if (p == n) + { + // On Win32 translate the root path to the special empty path. + // Search for root_scope for details. + // +#ifdef _WIN32 + path dir (name != "/" ? path (name) : path ()); +#else + path dir (name); +#endif + if (dp != nullptr) + dir = *dp / dir; + + ns.emplace_back ((tp != nullptr ? *tp : string ()), + move (dir), + string ()); + } + else + ns.emplace_back ((tp != nullptr ? *tp : string ()), + (dp != nullptr ? *dp : path ()), + move (name)); + continue; } |