146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/gn/err.h"
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/gn/filesystem_utils.h"
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/gn/functions.h"
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/gn/parse_tree.h"
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/gn/scope.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "tools/gn/value.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace functions {
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace {
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Corresponds to the various values of "what" in the function call.
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)enum What {
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WHAT_FILE,
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WHAT_NAME,
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WHAT_EXTENSION,
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WHAT_DIR,
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WHAT_ABSPATH,
236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  WHAT_GEN_DIR,
246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  WHAT_OUT_DIR,
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Returns the directory containing the input (resolving it against the
286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// |current_dir|), regardless of whether the input is a directory or a file.
296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)SourceDir DirForInput(const SourceDir& current_dir,
306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                      const std::string& input_string) {
316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!input_string.empty() && input_string[input_string.size() - 1] == '/') {
326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // Input is a directory.
336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return current_dir.ResolveRelativeDir(input_string);
346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Input is a directory.
376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return current_dir.ResolveRelativeFile(input_string).GetDir();
386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)std::string GetOnePathInfo(const Settings* settings,
416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                           const SourceDir& current_dir,
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                           What what,
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                           const Value& input,
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                           Err* err) {
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!input.VerifyTypeIs(Value::STRING, err))
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return std::string();
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const std::string& input_string = input.string_value();
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (input_string.empty()) {
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    *err = Err(input, "Calling get_path_info on an empty string.");
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return std::string();
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (what) {
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WHAT_FILE: {
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return FindFilename(&input_string).as_string();
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WHAT_NAME: {
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::string file = FindFilename(&input_string).as_string();
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      size_t extension_offset = FindExtensionOffset(file);
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (extension_offset == std::string::npos)
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return file;
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Trim extension and dot.
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return file.substr(0, extension_offset - 1);
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WHAT_EXTENSION: {
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return FindExtension(&input_string).as_string();
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WHAT_DIR: {
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::StringPiece dir_incl_slash = FindDir(&input_string);
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (dir_incl_slash.empty())
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return std::string(".");
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // Trim slash since this function doesn't return trailing slashes. The
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // times we don't do this are if the result is "/" and "//" since those
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      // slashes can't be trimmed.
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (dir_incl_slash == "/")
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return std::string("/.");
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (dir_incl_slash == "//")
7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return std::string("//.");
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return dir_incl_slash.substr(0, dir_incl_slash.size() - 1).as_string();
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case WHAT_GEN_DIR: {
826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return DirectoryWithNoLastSlash(
836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          GetGenDirForSourceDir(settings,
846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                DirForInput(current_dir, input_string)));
856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    case WHAT_OUT_DIR: {
876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return DirectoryWithNoLastSlash(
886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          GetOutputDirForSourceDir(settings,
896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                   DirForInput(current_dir, input_string)));
906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WHAT_ABSPATH: {
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!input_string.empty() && input_string[input_string.size() - 1] == '/')
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return current_dir.ResolveRelativeDir(input_string).value();
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      else
9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return current_dir.ResolveRelativeFile(input_string).value();
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    default:
9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      NOTREACHED();
9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return std::string();
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kGetPathInfo[] = "get_path_info";
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kGetPathInfo_HelpShort[] =
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "get_path_info: Extract parts of a file or directory name.";
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kGetPathInfo_Help[] =
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "get_path_info: Extract parts of a file or directory name.\n"
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  get_path_info(input, what)\n"
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  The first argument is either a string representing a file or\n"
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  directory name, or a list of such strings. If the input is a list\n"
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  the return value will be a list containing the result of applying the\n"
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  rule to each item in the input.\n"
11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "Possible values for the \"what\" parameter\n"
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  \"file\"\n"
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      The substring after the last slash in the path, including the name\n"
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      and extension. If the input ends in a slash, the empty string will\n"
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      be returned.\n"
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar.txt\" => \"bar.txt\"\n"
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"bar.txt\" => \"bar.txt\"\n"
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/\" => \"\"\n"
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"\" => \"\"\n"
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  \"name\"\n"
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "     The substring of the file name not including the extension.\n"
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar.txt\" => \"bar\"\n"
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar\" => \"bar\"\n"
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/\" => \"\"\n"
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  \"extension\"\n"
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      The substring following the last period following the last slash,\n"
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      or the empty string if not found. The period is not included.\n"
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar.txt\" => \"txt\"\n"
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar\" => \"\"\n"
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  \"dir\"\n"
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      The directory portion of the name, not including the slash.\n"
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar.txt\" => \"foo\"\n"
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"//foo/bar\" => \"//foo\"\n"
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo\" => \".\"\n"
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      The result will never end in a slash, so if the resulting\n"
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      is empty, the system (\"/\") or source (\"//\") roots, a \".\"\n"
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      will be appended such that it is always legal to append a slash\n"
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      and a filename and get a valid path.\n"
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "  \"out_dir\"\n"
1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "      The output file directory corresponding to the path of the\n"
1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "      given file, not including a trailing slash.\n"
1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "        \"//foo/bar/baz.txt\" => \"//out/Default/obj/foo/bar\"\n"
1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "  \"gen_dir\"\n"
1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "      The generated file directory corresponding to the path of the\n"
1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "      given file, not including a trailing slash.\n"
1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "        \"//foo/bar/baz.txt\" => \"//out/Default/gen/foo/bar\"\n"
1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    "\n"
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  \"abspath\"\n"
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      The full absolute path name to the file or directory. It will be\n"
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      resolved relative to the currebt directory, and then the source-\n"
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      absolute version will be returned. If the input is system-\n"
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      absolute, the same input will be returned.\n"
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/bar.txt\" => \"//mydir/foo/bar.txt\"\n"
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"foo/\" => \"//mydir/foo/\"\n"
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"//foo/bar\" => \"//foo/bar\"  (already absolute)\n"
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "        \"/usr/include\" => \"/usr/include\"  (already absolute)\n"
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      If you want to make the path relative to another directory, or to\n"
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "      be system-absolute, see rebase_path().\n"
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "Examples\n"
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  sources = [ \"foo.cc\", \"foo.h\" ]\n"
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  result = get_path_info(source, \"abspath\")\n"
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  # result will be [ \"//mydir/foo.cc\", \"//mydir/foo.h\" ]\n"
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  result = get_path_info(\"//foo/bar/baz.cc\", \"dir\")\n"
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  # result will be \"//foo/bar\"\n"
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "\n"
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  # Extract the source-absolute directory name,\n"
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    "  result = get_path_info(get_path_info(path, \"dir\"), \"abspath\")\n";
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Value RunGetPathInfo(Scope* scope,
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     const FunctionCallNode* function,
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     const std::vector<Value>& args,
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     Err* err) {
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (args.size() != 2) {
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    *err = Err(function, "Expecting two arguments to get_path_info.");
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return Value();
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Extract the "what".
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!args[1].VerifyTypeIs(Value::STRING, err))
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return Value();
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  What what;
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (args[1].string_value() == "file") {
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    what = WHAT_FILE;
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (args[1].string_value() == "name") {
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    what = WHAT_NAME;
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (args[1].string_value() == "extension") {
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    what = WHAT_EXTENSION;
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (args[1].string_value() == "dir") {
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    what = WHAT_DIR;
2076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } else if (args[1].string_value() == "out_dir") {
2086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    what = WHAT_OUT_DIR;
2096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } else if (args[1].string_value() == "gen_dir") {
2106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    what = WHAT_GEN_DIR;
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (args[1].string_value() == "abspath") {
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    what = WHAT_ABSPATH;
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    *err = Err(args[1], "Unknown value for 'what'.");
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return Value();
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const SourceDir& current_dir = scope->GetSourceDir();
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (args[0].type() == Value::STRING) {
2206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return Value(function, GetOnePathInfo(scope->settings(), current_dir, what,
2216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                          args[0], err));
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (args[0].type() == Value::LIST) {
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::vector<Value>& input_list = args[0].list_value();
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    Value result(function, Value::LIST);
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (size_t i = 0; i < input_list.size(); i++) {
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      result.list_value().push_back(Value(function,
2276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          GetOnePathInfo(scope->settings(), current_dir, what,
2286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                         input_list[i], err)));
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (err->has_error())
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return Value();
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return result;
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  *err = Err(args[0], "Path must be a string or a list of strings.");
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return Value();
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace functions
240