filesystem_utils.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <algorithm> 868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/logging.h" 10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_util.h" 11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/utf_string_conversions.h" 12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "build/build_config.h" 13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/location.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "tools/gn/settings.h" 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/source_dir.h" 16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace { 18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochenum DotDisposition { 20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is just part of a filename and is not special. 21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOT_A_DIRECTORY, 22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is the current directory. 24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DIRECTORY_CUR, 25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The given dot is the first of a double dot that should take us up one. 27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DIRECTORY_UP 28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}; 29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// When we find a dot, this function is called with the character following 31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// that dot to see what it is. The return value indicates what type this dot is 32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// (see above). This code handles the case where the dot is at the end of the 33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// input. 34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// 35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// |*consumed_len| will contain the number of characters in the input that 36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// express what we found. 37d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochDotDisposition ClassifyAfterDot(const std::string& path, 38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t after_dot, 39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t* consumed_len) { 40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (after_dot == path.size()) { 41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Single dot at the end. 42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 1; 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_CUR; 44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot] == '/') { 46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Single dot followed by a slash. 47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 2; // Consume the slash 48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_CUR; 49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot] == '.') { 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two dots. 53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (after_dot + 1 == path.size()) { 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Double dot at the end. 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 2; 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_UP; 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[after_dot + 1] == '/') { 59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Double dot folowed by a slash. 60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 3; 61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return DIRECTORY_UP; 62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The dots are followed by something else, not a directory. 66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *consumed_len = 1; 67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return NOT_A_DIRECTORY; 68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_WIN) 71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)inline char NormalizeWindowsPathChar(char c) { 72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (c == '/') 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return '\\'; 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return base::ToLowerASCII(c); 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Attempts to do a case and slash-insensitive comparison of two 8-bit Windows 78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// paths. 79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool AreAbsoluteWindowsPathsEqual(const base::StringPiece& a, 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const base::StringPiece& b) { 81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (a.size() != b.size()) 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // For now, just do a case-insensitive ASCII comparison. We could convert to 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // UTF-16 and use ICU if necessary. Or maybe base::strcasecmp is good enough? 86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) for (size_t i = 0; i < a.size(); i++) { 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (NormalizeWindowsPathChar(a[i]) != NormalizeWindowsPathChar(b[i])) 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool DoesBeginWindowsDriveLetter(const base::StringPiece& path) { 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (path.size() < 3) 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Check colon first, this will generally fail fastest. 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (path[1] != ':') 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Check drive letter 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!((path[0] >= 'A' && path[0] <= 'Z') || 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path[0] >= 'a' && path[0] <= 'z')) 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (path[2] != '/' && path[2] != '\\') 107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif 111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace 113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 114d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochSourceFileType GetSourceFileType(const SourceFile& file, 115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Settings::TargetOS os) { 116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch base::StringPiece extension = FindExtension(&file.value()); 117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "cc" || extension == "cpp" || extension == "cxx") 118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_CC; 119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "h") 120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_H; 121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "c") 122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_C; 123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (os) { 125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::MAC: 126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "m") 127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_M; 128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "mm") 129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_MM; 130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::WIN: 133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension == "rc") 134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_RC; 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(brettw) asm files. 136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (os != Settings::WIN) { 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (extension == "S") 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return SOURCE_S; 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return SOURCE_UNKNOWN; 148d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetExtensionForOutputType(Target::OutputType type, 151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Settings::TargetOS os) { 152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (os) { 1532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Settings::MAC: 1542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch switch (type) { 1552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::EXECUTABLE: 1562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return ""; 1572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::SHARED_LIBRARY: 1582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "dylib"; 1592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch case Target::STATIC_LIBRARY: 1602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return "a"; 1612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch default: 1622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch NOTREACHED(); 1632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 1642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch break; 1652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Settings::WIN: 167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (type) { 168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::EXECUTABLE: 169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "exe"; 170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::SHARED_LIBRARY: 171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "dll.lib"; // Extension of import library. 172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case Target::STATIC_LIBRARY: 173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return "lib"; 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) default: 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NOTREACHED(); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Settings::LINUX: 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) switch (type) { 1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Target::EXECUTABLE: 1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return ""; 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Target::SHARED_LIBRARY: 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return "so"; 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) case Target::STATIC_LIBRARY: 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return "a"; 187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch default: 193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch NOTREACHED(); 194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ""; 196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string FilePathToUTF8(const base::FilePath::StringType& str) { 199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return WideToUTF8(str); 201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return str; 203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::FilePath UTF8ToFilePath(const base::StringPiece& sp) { 207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::FilePath(UTF8ToWide(sp)); 209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#else 210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::FilePath(sp.as_string()); 211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochsize_t FindExtensionOffset(const std::string& path) { 215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (int i = static_cast<int>(path.size()); i >= 0; i--) { 216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '/') 217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '.') 219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return i + 1; 220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return std::string::npos; 222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindExtension(const std::string* path) { 225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t extension_offset = FindExtensionOffset(*path); 226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension_offset == std::string::npos) 227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&path->data()[extension_offset], 229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->size() - extension_offset); 230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochsize_t FindFilenameOffset(const std::string& path) { 233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) { 234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path[i] == '/') 235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return i + 1; 236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return 0; // No filename found means everything was the filename. 238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindFilename(const std::string* path) { 241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (filename_offset == 0) 243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(*path); // Everything is the file name. 244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&(*path).data()[filename_offset], 245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->size() - filename_offset); 246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindFilenameNoExtension(const std::string* path) { 249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path->empty()) 250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t extension_offset = FindExtensionOffset(*path); 253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t name_len; 255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (extension_offset == std::string::npos) 256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch name_len = path->size() - filename_offset; 257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch else 258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch name_len = extension_offset - filename_offset - 1; 259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(&(*path).data()[filename_offset], name_len); 261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid RemoveFilename(std::string* path) { 264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->resize(FindFilenameOffset(*path)); 265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EndsWithSlash(const std::string& s) { 268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return !s.empty() && s[s.size() - 1] == '/'; 269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbase::StringPiece FindDir(const std::string* path) { 272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t filename_offset = FindFilenameOffset(*path); 273d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (filename_offset == 0u) 274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(); 275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return base::StringPiece(path->data(), filename_offset); 276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EnsureStringIsInOutputDir(const SourceDir& dir, 279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& str, 280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const Value& originating, 281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Err* err) { 282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The last char of the dir will be a slash. We don't care if the input ends 283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // in a slash or not, so just compare up until there. 284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // 285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This check will be wrong for all proper prefixes "e.g. "/output" will 286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // match "/out" but we don't really care since this is just a sanity check. 287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string& dir_str = dir.value(); 288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (str.compare(0, dir_str.length() - 1, dir_str, 0, dir_str.length() - 1) 289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch != 0) { 290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch *err = Err(originating, "File not inside output directory.", 291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "The given file should be in the output directory. Normally you would " 292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "specify\n\"$target_output_dir/foo\" or " 293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "\"$target_gen_dir/foo\". I interpreted this as\n\"" 294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch + str + "\"."); 295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return false; 296d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return true; 298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsPathAbsolute(const base::StringPiece& path) { 3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.empty()) 3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path[0] != '/') { 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN) 3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Check for Windows system paths like "C:\foo". 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.size() > 2 && 3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) path[1] == ':' && (path[2] == '/' || path[2] == '\\')) 3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; // Doesn't begin with a slash, is relative. 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.size() > 1 && path[1] == '/') 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; // Double slash at the beginning means source-relative. 3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root, 3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::StringPiece& path, 3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string* dest) { 3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(IsPathAbsolute(source_root)); 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(IsPathAbsolute(path)); 3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dest->clear(); 3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (source_root.size() > path.size()) 3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; // The source root is longer: the path can never be inside. 3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN) 3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Source root should be canonical on Windows. 3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(source_root.size() > 2 && source_root[0] != '/' && 3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) source_root[1] == ':' && source_root[2] =='\\'); 335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) size_t after_common_index = std::string::npos; 337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (DoesBeginWindowsDriveLetter(path)) { 338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Handle "C:\foo" 339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (AreAbsoluteWindowsPathsEqual(source_root, 340424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path.substr(0, source_root.size()))) 341424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) after_common_index = source_root.size(); 342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 343424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 344424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else if (path[0] == '/' && source_root.size() <= path.size() - 1 && 345424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DoesBeginWindowsDriveLetter(path.substr(1))) { 346424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Handle "/C:/foo" 347424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (AreAbsoluteWindowsPathsEqual(source_root, 348424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path.substr(1, source_root.size()))) 349424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) after_common_index = source_root.size() + 1; 350424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 353424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 354424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 355424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 356424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If we get here, there's a match and after_common_index identifies the 357424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // part after it. 358424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 359424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The base may or may not have a trailing slash, so skip all slashes from 360424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the path after our prefix match. 361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) size_t first_after_slash = after_common_index; 362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) while (first_after_slash < path.size() && 363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) (path[first_after_slash] == '/' || path[first_after_slash] == '\\')) 364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) first_after_slash++; 365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->assign("//"); // Result is source root relative. 367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->append(&path.data()[first_after_slash], 368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path.size() - first_after_slash); 369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#else 372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // On non-Windows this is easy. Since we know both are absolute, just do a 3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // prefix check. 3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (path.substr(0, source_root.size()) == source_root) { 3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The base may or may not have a trailing slash, so skip all slashes from 3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the path after our prefix match. 3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t first_after_slash = source_root.size(); 3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (first_after_slash < path.size() && path[first_after_slash] == '/') 3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) first_after_slash++; 3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 382424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->assign("//"); // Result is source root relative. 3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dest->append(&path.data()[first_after_slash], 3843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) path.size() - first_after_slash); 3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 388424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif 3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 391d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string InvertDir(const SourceDir& path) { 392d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch const std::string value = path.value(); 393d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value.empty()) 394d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return std::string(); 395d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 396d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch DCHECK(value[0] == '/'); 397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t begin_index = 1; 398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 399d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // If the input begins with two slashes, skip over both (this is a 400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // source-relative dir). 401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value.size() > 1 && value[1] == '/') 402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch begin_index = 2; 403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 404d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string ret; 405d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = begin_index; i < value.size(); i++) { 406d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (value[i] == '/') 407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ret.append("../"); 408d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 409d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ret; 410d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 411d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 412d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NormalizePath(std::string* path) { 413d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch char* pathbuf = path->empty() ? NULL : &(*path)[0]; 414d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 415d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // top_index is the first character we can modify in the path. Anything 416d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // before this indicates where the path is relative to. 417d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t top_index = 0; 418d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch bool is_relative = true; 419d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!path->empty() && pathbuf[0] == '/') { 420d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch is_relative = false; 421d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (path->size() > 1 && pathbuf[1] == '/') { 423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two leading slashes, this is a path into the source dir. 424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = 2; 425d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 426d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // One leading slash, this is a system-absolute path. 427d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = 1; 428d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 429d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 430d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 431d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t dest_i = top_index; 432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t src_i = top_index; src_i < path->size(); /* nothing */) { 433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (pathbuf[src_i] == '.') { 434d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (src_i == 0 || pathbuf[src_i - 1] == '/') { 435d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Slash followed by a dot, see if it's something special. 436d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch size_t consumed_len; 437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) { 438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case NOT_A_DIRECTORY: 439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Copy the dot to the output, it means nothing special. 440d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 441d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 442d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case DIRECTORY_CUR: 443d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Current directory, just skip the input. 444d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i += consumed_len; 445d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch break; 446d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch case DIRECTORY_UP: 447d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Back up over previous directory component. If we're already 448d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // at the top, preserve the "..". 449d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (dest_i > top_index) { 450d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // The previous char was a slash, remove it. 451d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_i--; 452d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 453d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 454d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (dest_i == top_index) { 455d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (is_relative) { 456d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // We're already at the beginning of a relative input, copy the 457d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // ".." and continue. We need the trailing slash if there was 458d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // one before (otherwise we're at the end of the input). 459d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '.'; 460d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '.'; 461d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (consumed_len == 3) 462d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = '/'; 463d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 464d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // This also makes a new "root" that we can't delete by going 465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // up more levels. Otherwise "../.." would collapse to 466d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // nothing. 467d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch top_index = dest_i; 468d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 469d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Otherwise we're at the beginning of an absolute path. Don't 470d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // allow ".." to go up another level and just eat it. 471d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 472d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Just find the previous slash or the beginning of input. 473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch while (dest_i > 0 && pathbuf[dest_i - 1] != '/') 474d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch dest_i--; 475d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 476d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i += consumed_len; 477d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 478d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 479d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Dot not preceeded by a slash, copy it literally. 480d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 481d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 482d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else if (pathbuf[src_i] == '/') { 483d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (src_i > 0 && pathbuf[src_i - 1] == '/') { 484d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Two slashes in a row, skip over it. 485d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch src_i++; 486d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 487d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Just one slash, copy it. 488d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 489d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 490d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } else { 491d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Input nothing special, just copy it. 492d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch pathbuf[dest_i++] = pathbuf[src_i++]; 493d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 494d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 495d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch path->resize(dest_i); 496d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 497d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 498d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid ConvertPathToSystem(std::string* path) { 499d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#if defined(OS_WIN) 500d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch for (size_t i = 0; i < path->size(); i++) { 501d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if ((*path)[i] == '/') 502d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch (*path)[i] = '\\'; 503d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 504d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#endif 505d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 506d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 507d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string PathToSystem(const std::string& path) { 508d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string ret(path); 509d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ConvertPathToSystem(&ret); 510d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return ret; 511d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch} 512d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string RebaseSourceAbsolutePath(const std::string& input, 51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const SourceDir& dest_dir) { 51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) CHECK(input.size() >= 2 && input[0] == '/' && input[1] == '/') 51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) << "Input to rebase isn't source-absolute: " << input; 51768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) CHECK(dest_dir.is_source_absolute()) 51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) << "Dir to rebase to isn't source-absolute: " << dest_dir.value(); 51968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 52068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& dest = dest_dir.value(); 52168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 52268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Skip the common prefixes of the source and dest as long as they end in 52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // a [back]slash. 52468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t common_prefix_len = 2; // The beginning two "//" are always the same. 52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t max_common_length = std::min(input.size(), dest.size()); 52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = common_prefix_len; i < max_common_length; i++) { 52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if ((input[i] == '/' || input[i] == '\\') && 52868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (dest[i] == '/' || dest[i] == '\\')) 52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) common_prefix_len = i + 1; 53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) else if (input[i] != dest[i]) 53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 53268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 53368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 53468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Invert the dest dir starting from the end of the common prefix. 53568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string ret; 53668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = common_prefix_len; i < dest.size(); i++) { 53768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (dest[i] == '/' || dest[i] == '\\') 53868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret.append("../"); 53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Append any remaining unique input. 54268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret.append(&input[common_prefix_len], input.size() - common_prefix_len); 54368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 54468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // If the result is still empty, the paths are the same. 54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ret.empty()) 54668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ret.push_back('.'); 54768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 54868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return ret; 54968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string DirectoryWithNoLastSlash(const SourceDir& dir) { 552f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string ret; 553f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 554f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (dir.value().empty()) { 555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Just keep input the same. 556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (dir.value() == "/") { 557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.assign("/."); 558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (dir.value() == "//") { 559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.assign("//."); 560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.assign(dir.value()); 562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.resize(ret.size() - 1); 563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return ret; 565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetToolchainOutputDir(const Settings* settings) { 568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const OutputFile& toolchain_subdir = settings->toolchain_output_subdir(); 569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string result = settings->build_settings()->build_dir().value(); 571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!toolchain_subdir.value().empty()) 572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.append(toolchain_subdir.value()); 573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &result); 575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetToolchainGenDir(const Settings* settings) { 578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const OutputFile& toolchain_subdir = settings->toolchain_output_subdir(); 579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string result = settings->build_settings()->build_dir().value(); 581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!toolchain_subdir.value().empty()) 582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.append(toolchain_subdir.value()); 583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result.append("gen/"); 585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &result); 586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetOutputDirForSourceDir(const Settings* settings, 589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const SourceDir& source_dir) { 590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SourceDir toolchain = GetToolchainOutputDir(settings); 591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string ret; 593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) toolchain.SwapValue(&ret); 594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.append("obj/"); 595f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 596f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The source dir should be source-absolute, so we trim off the two leading 597f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // slashes to append to the toolchain object directory. 598f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(source_dir.is_source_absolute()); 599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.append(&source_dir.value()[2], source_dir.value().size() - 2); 600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &ret); 602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetGenDirForSourceDir(const Settings* settings, 605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const SourceDir& source_dir) { 606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SourceDir toolchain = GetToolchainGenDir(settings); 607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string ret; 609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) toolchain.SwapValue(&ret); 610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The source dir should be source-absolute, so we trim off the two leading 612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // slashes to append to the toolchain object directory. 613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(source_dir.is_source_absolute()); 614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ret.append(&source_dir.value()[2], source_dir.value().size() - 2); 615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SourceDir(SourceDir::SWAP_IN, &ret); 617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetTargetOutputDir(const Target* target) { 620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetOutputDirForSourceDir(target->settings(), target->label().dir()); 621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetTargetGenDir(const Target* target) { 624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetGenDirForSourceDir(target->settings(), target->label().dir()); 625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetCurrentOutputDir(const Scope* scope) { 628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetOutputDirForSourceDir(scope->settings(), scope->GetSourceDir()); 629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SourceDir GetCurrentGenDir(const Scope* scope) { 632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); 633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 634