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/label.h"
6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/logging.h"
8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/parse_tree.h"
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/value.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace {
13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// We print user visible label names with no trailing slash after the
15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// directory name.
16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string DirWithNoTrailingSlash(const SourceDir& dir) {
17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Be careful not to trim if the input is just "/" or "//".
18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (dir.value().size() > 2)
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return dir.value().substr(0, dir.value().size() - 1);
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return dir.value();
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Given the separate-out input (everything before the colon) in the dep rule,
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// computes the final build rule. Sets err on failure. On success,
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// |*used_implicit| will be set to whether the implicit current directory was
26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// used. The value is used only for generating error messages.
27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool ComputeBuildLocationFromDep(const Value& input_value,
28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                 const SourceDir& current_dir,
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                 const base::StringPiece& input,
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                 SourceDir* result,
31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                 Err* err) {
32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // No rule, use the current locaton.
33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (input.empty()) {
34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *result = current_dir;
35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return true;
36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Don't allow directories to start with a single slash. All labels must be
39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // in the source root.
40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (input[0] == '/' && (input.size() == 1 || input[1] != '/')) {
41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(input_value, "Label can't start with a single slash",
42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "Labels must be either relative (no slash at the beginning) or be "
43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "absolute\ninside the source root (two slashes at the beginning).");
44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  *result = current_dir.ResolveRelativeDir(input);
48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Given the separated-out target name (after the colon) computes the final
52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// name, using the implicit name from the previously-generated
53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// computed_location if necessary. The input_value is used only for generating
54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// error messages.
55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool ComputeTargetNameFromDep(const Value& input_value,
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              const SourceDir& computed_location,
57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              const base::StringPiece& input,
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              std::string* result,
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              Err* err) {
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!input.empty()) {
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Easy case: input is specified, just use it.
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    result->assign(input.data(), input.size());
63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return true;
64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const std::string& loc = computed_location.value();
67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Use implicit name. The path will be "//", "//base/", "//base/i18n/", etc.
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (loc.size() <= 2) {
70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(input_value, "This dependency name is empty");
71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  size_t next_to_last_slash = loc.rfind('/', loc.size() - 2);
75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  DCHECK(next_to_last_slash != std::string::npos);
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  result->assign(&loc[next_to_last_slash + 1],
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                 loc.size() - next_to_last_slash - 2);
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// The original value is used only for error reporting, use the |input| as the
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// input to this function (which may be a substring of the original value when
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// we're parsing toolchains.
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch//
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// If the output toolchain vars are NULL, then we'll report an error if we
86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// find a toolchain specified (this is used when recursively parsing toolchain
87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// labels which themselves can't have toolchain specs).
88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch//
89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// We assume that the output variables are initialized to empty so we don't
90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// write them unless we need them to contain something.
91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch//
92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Returns true on success. On failure, the out* variables might be written to
93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// but shouldn't be used.
94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool Resolve(const SourceDir& current_dir,
95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             const Label& current_toolchain,
96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             const Value& original_value,
97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             const base::StringPiece& input,
98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             SourceDir* out_dir,
99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             std::string* out_name,
100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             SourceDir* out_toolchain_dir,
101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             std::string* out_toolchain_name,
102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             Err* err) {
103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // To workaround the problem that StringPiece operator[] doesn't return a ref.
104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const char* input_str = input.data();
105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  size_t path_separator = input.find_first_of(":(");
107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::StringPiece location_piece;
108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::StringPiece name_piece;
109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::StringPiece toolchain_piece;
110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (path_separator == std::string::npos) {
111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    location_piece = input;
112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Leave name & toolchain piece null.
113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    location_piece = base::StringPiece(&input_str[0], path_separator);
115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    size_t toolchain_separator = input.find('(', path_separator);
117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (toolchain_separator == std::string::npos) {
118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      name_piece = base::StringPiece(&input_str[path_separator + 1],
119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                     input.size() - path_separator - 1);
120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Leave location piece null.
121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    } else if (!out_toolchain_dir) {
122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Toolchain specified but not allows in this context.
123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      *err = Err(original_value, "Toolchain has a toolchain.",
124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          "Your toolchain definition (inside the parens) seems to itself "
125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          "have a\ntoolchain. Don't do this.");
126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return false;
127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    } else {
128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Name piece is everything between the two separators. Note that the
129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // separators may be the same (e.g. "//foo(bar)" which means empty name.
130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (toolchain_separator > path_separator) {
131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        name_piece = base::StringPiece(
132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            &input_str[path_separator + 1],
133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            toolchain_separator - path_separator - 1);
134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Toolchain name should end in a ) and this should be the end of the
137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // string.
138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (input[input.size() - 1] != ')') {
139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        *err = Err(original_value, "Bad toolchain name.",
140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            "Toolchain name must end in a \")\" at the end of the label.");
141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        return false;
142d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
143d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
144d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Subtract off the two parens to just get the toolchain name.
145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      toolchain_piece = base::StringPiece(
146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          &input_str[toolchain_separator + 1],
147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          input.size() - toolchain_separator - 2);
148d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Everything before the separator is the filename.
152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // We allow three cases:
153d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  //   Absolute:                "//foo:bar" -> /foo:bar
154d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  //   Target in current file:  ":foo"     -> <currentdir>:foo
155d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  //   Path with implicit name: "/foo"     -> /foo:foo
156d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (location_piece.empty() && name_piece.empty()) {
157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Can't use both implicit filename and name (":").
158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(original_value, "This doesn't specify a dependency.");
159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
162d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!ComputeBuildLocationFromDep(original_value, current_dir, location_piece,
163d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                   out_dir, err))
164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!ComputeTargetNameFromDep(original_value, *out_dir, name_piece,
167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                out_name, err))
168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Last, do the toolchains.
171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (out_toolchain_dir) {
172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Handle empty toolchain strings. We don't allow normal labels to be
173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // empty so we can't allow the recursive call of this function to do this
174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // check.
175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (toolchain_piece.empty()) {
176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      *out_toolchain_dir = current_toolchain.dir();
177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      *out_toolchain_name = current_toolchain.name();
178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return true;
179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    } else {
180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return Resolve(current_dir, current_toolchain,
181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                     original_value, toolchain_piece,
182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                     out_toolchain_dir, out_toolchain_name, NULL, NULL, err);
183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace
189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
190d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochLabel::Label() {
191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
193d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochLabel::Label(const SourceDir& dir,
194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             const base::StringPiece& name,
195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             const SourceDir& toolchain_dir,
196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch             const base::StringPiece& toolchain_name)
197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    : dir_(dir),
198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      toolchain_dir_(toolchain_dir) {
199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  name_.assign(name.data(), name.size());
200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  toolchain_name_.assign(toolchain_name.data(), toolchain_name.size());
201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Label::Label(const SourceDir& dir, const base::StringPiece& name)
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : dir_(dir) {
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  name_.assign(name.data(), name.size());
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
208d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochLabel::~Label() {
209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static
212d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochLabel Label::Resolve(const SourceDir& current_dir,
213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                     const Label& current_toolchain,
214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                     const Value& input,
215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                     Err* err) {
216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Label ret;
217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (input.type() != Value::STRING) {
218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(input, "Dependency is not a string.");
219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ret;
220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const std::string& input_string = input.string_value();
222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (input_string.empty()) {
223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(input, "Dependency string is empty.");
224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ret;
225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!::Resolve(current_dir, current_toolchain, input, input_string,
228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                 &ret.dir_, &ret.name_,
229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                 &ret.toolchain_dir_, &ret.toolchain_name_,
230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                 err))
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Label();
232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return ret;
233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
235d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochLabel Label::GetToolchainLabel() const {
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return Label(toolchain_dir_, toolchain_name_);
237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Label Label::GetWithNoToolchain() const {
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return Label(dir_, name_);
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string Label::GetUserVisibleName(bool include_toolchain) const {
244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::string ret;
245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ret.reserve(dir_.value().size() + name_.size() + 1);
246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (dir_.is_null())
248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ret;
249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ret = DirWithNoTrailingSlash(dir_);
251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ret.push_back(':');
252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ret.append(name_);
253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (include_toolchain) {
255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    ret.push_back('(');
256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!toolchain_dir_.is_null() && !toolchain_name_.empty()) {
257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      ret.append(DirWithNoTrailingSlash(toolchain_dir_));
258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      ret.push_back(':');
259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      ret.append(toolchain_name_);
260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    ret.push_back(')');
262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return ret;
264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochstd::string Label::GetUserVisibleName(const Label& default_toolchain) const {
267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  bool include_toolchain =
268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      default_toolchain.dir() != toolchain_dir_ ||
269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      default_toolchain.name() != toolchain_name_;
270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return GetUserVisibleName(include_toolchain);
271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
272