1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file. 4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/filesystem_utils.h" 6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/logging.h" 8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/utf_string_conversions.h" 9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "build/build_config.h" 10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/location.h" 11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/source_dir.h" 12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochenum DotDisposition { 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is just part of a filename and is not special. 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOT_A_DIRECTORY, 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is the current directory. 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DIRECTORY_CUR, 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is the first of a double dot that should take us up one. 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DIRECTORY_UP 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// When we find a dot, this function is called with the character following 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// that dot to see what it is. The return value indicates what type this dot is 28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// (see above). This code handles the case where the dot is at the end of the 29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// input. 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// |*consumed_len| will contain the number of characters in the input that 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// express what we found. 33d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochDotDisposition ClassifyAfterDot(const std::string& path, 34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t after_dot, 35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t* consumed_len) { 36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (after_dot == path.size()) { 37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Single dot at the end. 38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 1; 39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_CUR; 40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot] == '/') { 42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Single dot followed by a slash. 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 2; // Consume the slash 44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_CUR; 45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot] == '.') { 48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two dots. 49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (after_dot + 1 == path.size()) { 50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Double dot at the end. 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 2; 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_UP; 53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot + 1] == '/') { 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Double dot folowed by a slash. 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 3; 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_UP; 58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The dots are followed by something else, not a directory. 62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 1; 63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return NOT_A_DIRECTORY; 64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} // namesapce 67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 68d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochSourceFileType GetSourceFileType(const SourceFile& file, 69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Settings::TargetOS os) { 70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::StringPiece extension = FindExtension(&file.value()); 71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "cc" || extension == "cpp" || extension == "cxx") 72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_CC; 73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "h") 74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_H; 75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "c") 76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_C; 77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (os) { 79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::MAC: 80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "m") 81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_M; 82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "mm") 83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_MM; 84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::WIN: 87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "rc") 88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_RC; 89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) asm files. 96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // TODO(brettw) weird thing with .S on non-Windows platforms. 97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_UNKNOWN; 98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetExtensionForOutputType(Target::OutputType type, 101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Settings::TargetOS os) { 102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (os) { 1032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Settings::MAC: 1042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch switch (type) { 1052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::NONE: 1062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch NOTREACHED(); 1072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return ""; 1082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::EXECUTABLE: 1092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return ""; 1102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::SHARED_LIBRARY: 1112385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "dylib"; 1122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::STATIC_LIBRARY: 1132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "a"; 1142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::LOADABLE_MODULE: 1152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "dylib"; // TODO(brettw) what's this? 1162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch default: 1172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch NOTREACHED(); 1182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 1192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch break; 1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::WIN: 122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (type) { 123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::NONE: 124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ""; 126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::EXECUTABLE: 127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "exe"; 128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::SHARED_LIBRARY: 129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "dll.lib"; // Extension of import library. 130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::STATIC_LIBRARY: 131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "lib"; 132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::LOADABLE_MODULE: 133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "dll"; // TODO(brettw) what's this? 134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 142d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ""; 143d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 144d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string FilePathToUTF8(const base::FilePath& path) { 146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return WideToUTF8(path.value()); 148d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return path.value(); 150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 153d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::FilePath UTF8ToFilePath(const base::StringPiece& sp) { 154d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 155d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::FilePath(UTF8ToWide(sp)); 156d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::FilePath(sp.as_string()); 158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochsize_t FindExtensionOffset(const std::string& path) { 162d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (int i = static_cast<int>(path.size()); i >= 0; i--) { 163d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '/') 164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '.') 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return i + 1; 167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return std::string::npos; 169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindExtension(const std::string* path) { 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t extension_offset = FindExtensionOffset(*path); 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension_offset == std::string::npos) 174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&path->data()[extension_offset], 176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->size() - extension_offset); 177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochsize_t FindFilenameOffset(const std::string& path) { 180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) { 181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '/') 182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return i + 1; 183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return 0; // No filename found means everything was the filename. 185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindFilename(const std::string* path) { 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (filename_offset == 0) 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(*path); // Everything is the file name. 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&(*path).data()[filename_offset], 192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->size() - filename_offset); 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindFilenameNoExtension(const std::string* path) { 196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path->empty()) 197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t extension_offset = FindExtensionOffset(*path); 200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t name_len; 202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension_offset == std::string::npos) 203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch name_len = path->size() - filename_offset; 204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch else 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch name_len = extension_offset - filename_offset - 1; 206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&(*path).data()[filename_offset], name_len); 208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid RemoveFilename(std::string* path) { 211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->resize(FindFilenameOffset(*path)); 212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EndsWithSlash(const std::string& s) { 215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return !s.empty() && s[s.size() - 1] == '/'; 216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindDir(const std::string* path) { 219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (filename_offset == 0u) 221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(path->data(), filename_offset); 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EnsureStringIsInOutputDir(const SourceDir& dir, 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& str, 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Value& originating, 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The last char of the dir will be a slash. We don't care if the input ends 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // in a slash or not, so just compare up until there. 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This check will be wrong for all proper prefixes "e.g. "/output" will 233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // match "/out" but we don't really care since this is just a sanity check. 234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& dir_str = dir.value(); 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (str.compare(0, dir_str.length() - 1, dir_str, 0, dir_str.length() - 1) 236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch != 0) { 237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err = Err(originating, "File not inside output directory.", 238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "The given file should be in the output directory. Normally you would " 239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "specify\n\"$target_output_dir/foo\" or " 240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "\"$target_gen_dir/foo\". I interpreted this as\n\"" 241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch + str + "\"."); 242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return false; 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return true; 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string InvertDir(const SourceDir& path) { 248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string value = path.value(); 249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value.empty()) 250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return std::string(); 251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(value[0] == '/'); 253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t begin_index = 1; 254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // If the input begins with two slashes, skip over both (this is a 256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // source-relative dir). 257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value.size() > 1 && value[1] == '/') 258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch begin_index = 2; 259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string ret; 261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = begin_index; i < value.size(); i++) { 262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value[i] == '/') 263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ret.append("../"); 264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ret; 266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NormalizePath(std::string* path) { 269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch char* pathbuf = path->empty() ? NULL : &(*path)[0]; 270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // top_index is the first character we can modify in the path. Anything 272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // before this indicates where the path is relative to. 273d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t top_index = 0; 274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bool is_relative = true; 275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!path->empty() && pathbuf[0] == '/') { 276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch is_relative = false; 277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path->size() > 1 && pathbuf[1] == '/') { 279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two leading slashes, this is a path into the source dir. 280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = 2; 281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // One leading slash, this is a system-absolute path. 283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = 1; 284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t dest_i = top_index; 288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t src_i = top_index; src_i < path->size(); /* nothing */) { 289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (pathbuf[src_i] == '.') { 290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (src_i == 0 || pathbuf[src_i - 1] == '/') { 291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Slash followed by a dot, see if it's something special. 292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t consumed_len; 293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) { 294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case NOT_A_DIRECTORY: 295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Copy the dot to the output, it means nothing special. 296d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case DIRECTORY_CUR: 299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Current directory, just skip the input. 300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i += consumed_len; 301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case DIRECTORY_UP: 303d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Back up over previous directory component. If we're already 304d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // at the top, preserve the "..". 305d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (dest_i > top_index) { 306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The previous char was a slash, remove it. 307d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_i--; 308d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 309d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (dest_i == top_index) { 311d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (is_relative) { 312d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // We're already at the beginning of a relative input, copy the 313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // ".." and continue. We need the trailing slash if there was 314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // one before (otherwise we're at the end of the input). 315d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '.'; 316d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '.'; 317d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (consumed_len == 3) 318d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '/'; 319d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 320d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This also makes a new "root" that we can't delete by going 321d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // up more levels. Otherwise "../.." would collapse to 322d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // nothing. 323d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = dest_i; 324d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 325d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Otherwise we're at the beginning of an absolute path. Don't 326d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // allow ".." to go up another level and just eat it. 327d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 328d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Just find the previous slash or the beginning of input. 329d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch while (dest_i > 0 && pathbuf[dest_i - 1] != '/') 330d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_i--; 331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 332d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i += consumed_len; 333d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 334d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 335d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Dot not preceeded by a slash, copy it literally. 336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 338d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if (pathbuf[src_i] == '/') { 339d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (src_i > 0 && pathbuf[src_i - 1] == '/') { 340d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two slashes in a row, skip over it. 341d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i++; 342d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 343d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Just one slash, copy it. 344d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 345d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 346d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Input nothing special, just copy it. 348d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 349d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 350d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->resize(dest_i); 352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 353d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid ConvertPathToSystem(std::string* path) { 355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 356d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < path->size(); i++) { 357d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if ((*path)[i] == '/') 358d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch (*path)[i] = '\\'; 359d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 360d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 361d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 362d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 363d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string PathToSystem(const std::string& path) { 364d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string ret(path); 365d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ConvertPathToSystem(&ret); 366d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ret; 367d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 368d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 369