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/functions.h"
6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <iostream>
8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/environment.h"
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_util.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config.h"
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config_values_generator.h"
13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/input_file.h"
15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/parse_tree.h"
16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scope.h"
18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/settings.h"
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "tools/gn/template.h"
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/token.h"
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/value.h"
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingImport(const ParseNode* node,
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               const Scope* scope,
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               Err* err) {
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (scope->IsProcessingImport()) {
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(node, "Not valid from an import.",
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        "Imports are for defining defaults, variables, and rules. The\n"
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        "appropriate place for this kind of thing is really in a normal\n"
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "BUILD file.");
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingBuildConfig(const ParseNode* node,
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const Scope* scope,
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    Err* err) {
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (scope->IsProcessingBuildConfig()) {
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(node, "Not valid from the build config.",
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "You can't do this kind of thing from the build config script, "
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "silly!\nPut it in a regular BUILD file.");
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool FillTargetBlockScope(const Scope* scope,
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const FunctionCallNode* function,
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          const std::string& target_type,
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const BlockNode* block,
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const std::vector<Value>& args,
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          Scope* block_scope,
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          Err* err) {
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!block) {
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    FillNeedsBlockError(function, err);
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Copy the target defaults, if any, into the scope we're going to execute
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the block in.
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Scope* default_scope = scope->GetTargetDefaults(target_type);
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (default_scope) {
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Scope::MergeOptions merge_options;
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    merge_options.skip_private_vars = true;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!default_scope->NonRecursiveMergeTo(block_scope, merge_options,
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            function, "target defaults", err))
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return false;
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The name is the single argument to the target function.
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!EnsureSingleStringArg(function, args, err))
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Set the target name variable to the current target, and mark it used
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // because we don't want to issue an error if the script ignores it.
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const base::StringPiece target_name("target_name");
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block_scope->SetValue(target_name, Value(function, args[0].string_value()),
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        function);
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block_scope->MarkUsed(target_name);
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *err = Err(function->function(), "This function call requires a block.",
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "The block's \"{\" must be on the same line as the function "
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "call's \")\".");
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureSingleStringArg(const FunctionCallNode* function,
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           const std::vector<Value>& args,
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           Err* err) {
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (args.size() != 1) {
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(function->function(), "Incorrect arguments.",
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               "This function requires a single string argument.");
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return args[0].VerifyTypeIs(Value::STRING, err);
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const Label& ToolchainLabelForScope(const Scope* scope) {
1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return scope->settings()->toolchain_label();
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Label MakeLabelForScope(const Scope* scope,
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const FunctionCallNode* function,
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const std::string& name) {
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Label& toolchain_label = ToolchainLabelForScope(scope);
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Label(scope->GetSourceDir(), name, toolchain_label.dir(),
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               toolchain_label.name());
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace functions {
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// assert ----------------------------------------------------------------------
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert[] = "assert";
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kAssert_HelpShort[] =
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "assert: Assert an expression is true at generation time.";
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert_Help[] =
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "assert: Assert an expression is true at generation time.\n"
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  assert(<condition> [, <error string>])\n"
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  If the condition is false, the build will fail with an error. If the\n"
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  optional second argument is provided, that string will be printed\n"
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  with the error message.\n"
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Examples:\n"
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  assert(is_win)\n"
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  assert(defined(sources), \"Sources must be defined\")\n";
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunAssert(Scope* scope,
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const FunctionCallNode* function,
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (args.size() != 1 && args.size() != 2) {
138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Wrong number of arguments.",
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               "assert() takes one or two argument, "
140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "were you expecting somethig else?");
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (args[0].type() != Value::BOOLEAN) {
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *err = Err(function->function(), "Assertion value not a bool.");
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (!args[0].boolean_value()) {
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (args.size() == 2) {
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      // Optional string message.
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (args[1].type() != Value::STRING) {
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *err = Err(function->function(), "Assertion failed.",
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            "<<<ERROR MESSAGE IS NOT A STRING>>>");
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      } else {
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *err = Err(function->function(), "Assertion failed.",
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            args[1].string_value());
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else {
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *err = Err(function->function(), "Assertion failed.");
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (args[0].origin()) {
158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // If you do "assert(foo)" we'd ideally like to show you where foo was
159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // set, and in this case the origin of the args will tell us that.
160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // However, if you do "assert(foo && bar)" the source of the value will
161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // be the assert like, which isn't so helpful.
162d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      //
163d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // So we try to see if the args are from the same line or not. This will
164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // break if you do "assert(\nfoo && bar)" and we may show the second line
165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // as the source, oh well. The way around this is to check to see if the
166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // origin node is inside our function call block.
167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      Location origin_location = args[0].origin()->GetRange().begin();
168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (origin_location.file() != function->function().location().file() ||
169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          origin_location.line_number() !=
170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch              function->function().location().line_number()) {
171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              "This is where it was set."));
173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// config ----------------------------------------------------------------------
180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig[] = "config";
182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kConfig_HelpShort[] =
183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "config: Defines a configuration object.";
184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig_Help[] =
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "config: Defines a configuration object.\n"
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  Configuration objects can be applied to targets and specify sets of\n"
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  compiler flags, includes, defines, etc. They provide a way to\n"
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  conveniently group sets of this configuration information.\n"
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  A config is referenced by its label just like a target.\n"
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  The values in a config are additive only. If you want to remove a flag\n"
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  you need to remove the corresponding config that sets it. The final\n"
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  set of flags, defines, etc. for a target is generated in this order:\n"
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "   1. The values specified directly on the target (rather than using a\n"
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "      config.\n"
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "   2. The configs specified in the target's \"configs\" list, in order.\n"
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   3. Public_configs from a breadth-first traversal of the dependency\n"
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      tree in the order that the targets appear in \"deps\".\n"
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "   4. All dependent configs from a breadth-first traversal of the\n"
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "      dependency tree in the order that the targets appear in \"deps\".\n"
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "Variables valid in a config definition:\n"
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    CONFIG_VALUES_VARS_HELP
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "Variables on a target used to apply configs:\n"
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  all_dependent_configs, configs, public_configs,\n"
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  forward_dependent_configs_from\n"
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "Example:\n"
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  config(\"myconfig\") {\n"
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "    includes = [ \"include/common\" ]\n"
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "    defines = [ \"ENABLE_DOOM_MELON\" ]\n"
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  }\n"
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  executable(\"mything\") {\n"
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "    configs = [ \":myconfig\" ]\n"
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  }\n";
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunConfig(const FunctionCallNode* function,
223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Scope* scope,
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Label label(MakeLabelForScope(scope, function, args[0].string_value()));
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (g_scheduler->verbose_logging())
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    g_scheduler->Log("Defining config", label.GetUserVisibleName(true));
234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Create the new config.
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<Config> config(new Config(scope->settings(), label));
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  config->set_defined_from(function);
238e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!Visibility::FillItemVisibility(config.get(), scope, err))
239e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return Value();
240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Fill it.
2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const SourceDir& input_dir = scope->GetSourceDir();
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ConfigValuesGenerator gen(&config->config_values(), scope, input_dir, err);
244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  gen.Run();
245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Save the generated item.
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Scope::ItemVector* collector = scope->GetItemCollector();
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!collector) {
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    *err = Err(function, "Can't define a config in this context.");
252010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return Value();
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  collector->push_back(new scoped_ptr<Item>(config.PassAs<Item>()));
255010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declare_args ----------------------------------------------------------------
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs[] = "declare_args";
262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kDeclareArgs_HelpShort[] =
263e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "declare_args: Declare build arguments.";
264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs_Help[] =
265e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "declare_args: Declare build arguments.\n"
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  Introduces the given arguments into the current scope. If they are\n"
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  not specified on the command line or in a toolchain's arguments,\n"
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  the default values given in the declare_args block will be used.\n"
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  However, these defaults will not override command-line values.\n"
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  See also \"gn help buildargs\" for an overview.\n"
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Example:\n"
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  declare_args() {\n"
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    enable_teleporter = true\n"
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    enable_doom_melon = false\n"
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  }\n"
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  If you want to override the (default disabled) Doom Melon:\n"
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    gn --args=\"enable_doom_melon=true enable_teleporter=false\"\n"
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  This also sets the teleporter, but it's already defaulted to on so\n"
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  it will have no effect.\n";
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunDeclareArgs(Scope* scope,
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     const FunctionCallNode* function,
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     const std::vector<Value>& args,
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     BlockNode* block,
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     Err* err) {
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Scope block_scope(scope);
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  block->ExecuteBlockInScope(&block_scope, err);
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err->has_error())
293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Pass the values from our scope into the Args object for adding to the
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // scope with the proper values (taking into account the defaults given in
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the block_scope, and arguments passed into the build).
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Scope::KeyValueMap values;
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  block_scope.GetCurrentScopeValues(&values);
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scope->settings()->build_settings()->build_args().DeclareArgs(
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      values, scope, err);
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Value();
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// defined ---------------------------------------------------------------------
306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDefined[] = "defined";
308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kDefined_HelpShort[] =
309c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "defined: Returns whether an identifier is defined.";
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDefined_Help[] =
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "defined: Returns whether an identifier is defined.\n"
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  Returns true if the given argument is defined. This is most useful in\n"
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  templates to assert that the caller set things up properly.\n"
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  You can pass an identifier:\n"
317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "    defined(foo)\n"
318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  which will return true or false depending on whether foo is defined in\n"
319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  the current scope.\n"
320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "\n"
321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  You can also check a named scope:\n"
322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "    defined(foo.bar)\n"
323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  which returns true if both foo is defined and bar is defined on the\n"
324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  named scope foo. It will throw an error if foo is defined but is not\n"
325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "  a scope.\n"
326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "\n"
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Example:\n"
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  template(\"mytemplate\") {\n"
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    # To help users call this template properly...\n"
331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "    assert(defined(invoker.sources), \"Sources must be defined\")\n"
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    # If we want to accept an optional \"values\" argument, we don't\n"
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    # want to dereference something that may not be defined.\n"
335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "    if (defined(invoker.values)) {\n"
336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "      values = invoker.values\n"
337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "    } else {\n"
338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    "      values = \"some default value\"\n"
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    }\n"
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  }\n";
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunDefined(Scope* scope,
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 const FunctionCallNode* function,
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 const ListNode* args_list,
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 Err* err) {
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const std::vector<const ParseNode*>& args_vector = args_list->contents();
347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (args_vector.size() != 1) {
348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    *err = Err(function, "Wrong number of arguments to defined().",
349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               "Expecting exactly one.");
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
354effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (identifier) {
355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Passed an identifier "defined(foo)".
356effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (scope->GetValue(identifier->value().value()))
357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return Value(function, true);
358effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return Value(function, false);
359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const AccessorNode* accessor = args_vector[0]->AsAccessor();
362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (accessor) {
363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Passed an accessor "defined(foo.bar)".
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (accessor->member()) {
365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // The base of the accessor must be a scope if it's defined.
366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const Value* base = scope->GetValue(accessor->base().value());
367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (!base)
368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return Value(function, false);
369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (!base->VerifyTypeIs(Value::SCOPE, err))
370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return Value();
371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      // Check the member inside the scope to see if its defined.
373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (base->scope_value()->GetValue(accessor->member()->value().value()))
374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        return Value(function, true);
375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return Value(function, false);
376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Argument is invalid.
380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  *err = Err(function, "Bad thing passed to defined().",
381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      "It should be of the form defined(foo) or defined(foo.bar).");
382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return Value();
383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// getenv ----------------------------------------------------------------------
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kGetEnv[] = "getenv";
388e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kGetEnv_HelpShort[] =
389e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "getenv: Get an environment variable.";
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kGetEnv_Help[] =
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "getenv: Get an environment variable.\n"
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "\n"
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  value = getenv(env_var_name)\n"
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "\n"
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  Returns the value of the given enironment variable. If the value is\n"
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  not found, it will try to look up the variable with the \"opposite\"\n"
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  case (based on the case of the first letter of the variable), but\n"
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  is otherwise case-sensitive.\n"
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "\n"
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  If the environment variable is not found, the empty string will be\n"
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  returned. Note: it might be nice to extend this if we had the concept\n"
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  of \"none\" in the language to indicate lookup failure.\n"
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "\n"
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "Example:\n"
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "\n"
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  home_dir = getenv(\"HOME\")\n";
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Value RunGetEnv(Scope* scope,
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const FunctionCallNode* function,
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const std::vector<Value>& args,
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                Err* err) {
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!EnsureSingleStringArg(function, args, err))
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Value();
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string result;
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!env->GetVar(args[0].string_value().c_str(), &result))
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Value(function, "");  // Not found, return empty string.
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return Value(function, result);
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// import ----------------------------------------------------------------------
424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport[] = "import";
426e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kImport_HelpShort[] =
427e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "import: Import a file into the current scope.";
428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport_Help[] =
429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "import: Import a file into the current scope.\n"
430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  The import command loads the rules and variables resulting from\n"
432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  executing the given file into the current scope.\n"
433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  By convention, imported files are named with a .gni extension.\n"
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  An import is different than a C++ \"include\". The imported file is\n"
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  executed in a standalone environment from the caller of the import\n"
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  command. The results of this execution are cached for other files that\n"
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  import the same .gni file.\n"
440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  Note that you can not import a BUILD.gn file that's otherwise used\n"
442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  in the build. Files must either be imported or implicitly loaded as\n"
443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  a result of deps rules, but not both.\n"
444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  The imported file's scope will be merged with the scope at the point\n"
446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import was called. If there is a conflict (both the current scope and\n"
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  the imported file define some variable or rule with the same name but\n"
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  different value), a runtime error will be thrown. Therefore, it's good\n"
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "  practice to minimize the stuff that an imported file defines.\n"
450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "  Variables and templates beginning with an underscore '_' are\n"
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "  considered private and will not be imported. Imported files can use\n"
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "  such variables for internal computation without affecting other files.\n"
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    "\n"
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "Examples:\n"
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import(\"//build/rules/idl_compilation_rule.gni\")\n"
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  # Looks in the current directory.\n"
460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import(\"my_vars.gni\")\n";
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunImport(Scope* scope,
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const FunctionCallNode* function,
464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!EnsureSingleStringArg(function, args, err))
467d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
468d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const SourceDir& input_dir = scope->GetSourceDir();
470d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  SourceFile import_file =
471d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      input_dir.ResolveRelativeFile(args[0].string_value());
472d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->settings()->import_manager().DoImport(import_file, function,
473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                               scope, err);
474d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
475d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
476d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// set_sources_assignment_filter -----------------------------------------------
478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
480e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kSetSourcesAssignmentFilter_HelpShort[] =
481e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "set_sources_assignment_filter: Set a pattern to filter source files.";
482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter_Help[] =
48368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "set_sources_assignment_filter: Set a pattern to filter source files.\n"
48468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
48568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  The sources assignment filter is a list of patterns that remove files\n"
48668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  from the list implicitly whenever the \"sources\" variable is\n"
48768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  assigned to. This is intended to be used to globally filter out files\n"
48868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  with platform-specific naming schemes when they don't apply, for\n"
48968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  example, you may want to filter out all \"*_win.cc\" files on non-\n"
49068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  Windows platforms.\n"
49168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  Typically this will be called once in the master build config script\n"
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  to set up the filter for the current platform. Subsequent calls will\n"
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  overwrite the previous values.\n"
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
49668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  If you want to bypass the filter and add a file even if it might\n"
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  be filtered out, call set_sources_assignment_filter([]) to clear the\n"
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  list of filters. This will apply until the current scope exits\n"
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "\n"
5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "How to use patterns\n"
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  File patterns are VERY limited regular expressions. They must match\n"
5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  the entire input string to be counted as a match. In regular\n"
5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  expression parlance, there is an implicit \"^...$\" surrounding your\n"
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  input. If you want to match a substring, you need to use wildcards at\n"
5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  the beginning and end.\n"
5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  There are only two special tokens understood by the pattern matcher.\n"
5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  Everything else is a literal.\n"
5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   * Matches zero or more of any character. It does not depend on the\n"
5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "     preceding character (in regular expression parlance it is\n"
5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "     equivalent to \".*\").\n"
5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  \\b Matches a path boundary. This will match the beginning or end of\n"
5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "     a string, or a slash.\n"
5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "Pattern examples\n"
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  \"*asdf*\"\n"
5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Matches a string containing \"asdf\" anywhere.\n"
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  \"asdf\"\n"
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Matches only the exact string \"asdf\".\n"
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  \"*.cc\"\n"
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Matches strings ending in the literal \".cc\".\n"
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  \"\\bwin/*\"\n"
5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "      Matches \"win/foo\" and \"foo/win/bar.cc\" but not \"iwin/foo\".\n"
5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "Sources assignment example\n"
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "\n"
53468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    "  # Filter out all _win files.\n"
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  set_sources_assignment_filter([ \"*_win.cc\", \"*_win.h\" ])\n"
5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  sources = [ \"a.cc\", \"b_win.cc\" ]\n"
5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  print(sources)\n"
5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "  # Will print [ \"a.cc\" ]. b_win one was filtered out.\n";
539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunSetSourcesAssignmentFilter(Scope* scope,
541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const FunctionCallNode* function,
542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const std::vector<Value>& args,
543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    Err* err) {
544d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
545d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function, "set_sources_assignment_filter takes one argument.");
546d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
547d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<PatternList> f(new PatternList);
548d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    f->SetFromValue(args[0], err);
549d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!err->has_error())
550d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      scope->set_sources_assignment_filter(f.Pass());
551d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
552d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
553d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
554d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// print -----------------------------------------------------------------------
556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
557a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint[] = "print";
558e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kPrint_HelpShort[] =
559e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "print: Prints to the console.";
560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint_Help[] =
561e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "print: Prints to the console.\n"
562e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "\n"
563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  Prints all arguments to the console separated by spaces. A newline is\n"
564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  automatically appended to the end.\n"
565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  This function is intended for debugging. Note that build files are run\n"
567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  in parallel so you may get interleaved prints. A buildfile may also\n"
568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  be executed more than once in parallel in the context of different\n"
569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  toolchains so the prints from one file may be duplicated or\n"
570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  interleaved with itself.\n"
571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "Examples:\n"
573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  print(\"Hello world\")\n"
574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  print(sources, deps)\n";
576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunPrint(Scope* scope,
578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               const FunctionCallNode* function,
579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               const std::vector<Value>& args,
580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               Err* err) {
581c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::string output;
582d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (size_t i = 0; i < args.size(); i++) {
583d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (i != 0)
584c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      output.push_back(' ');
585c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    output.append(args[i].ToString(false));
586d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
587c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  output.push_back('\n');
588c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
589c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const BuildSettings::PrintCallback& cb =
590c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      scope->settings()->build_settings()->print_callback();
591c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cb.is_null())
592c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    printf("%s", output.c_str());
593c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  else
594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cb.Run(output);
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
596d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
597d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
598d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// -----------------------------------------------------------------------------
600d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
601a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo()
6023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
604a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
605a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
606e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help_short(NULL),
607e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help(NULL),
608e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      is_target(false) {
609d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
610d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
611e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochFunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf,
612e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help_short,
613e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help,
614e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           bool in_is_target)
6153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(seaf),
6163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
6173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      executed_block_runner(NULL),
6183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      no_block_runner(NULL),
619e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help_short(in_help_short),
620e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help(in_help),
621e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      is_target(in_is_target) {
6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
624e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochFunctionInfo::FunctionInfo(GenericBlockFunction gbf,
625e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help_short,
626e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help,
627e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           bool in_is_target)
6283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
6293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(gbf),
630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
632e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help_short(in_help_short),
633e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help(in_help),
634e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      is_target(in_is_target) {
635d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
636d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
637e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochFunctionInfo::FunctionInfo(ExecutedBlockFunction ebf,
638e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help_short,
639e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help,
640e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           bool in_is_target)
6413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
6423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
643a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(ebf),
644a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
645e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help_short(in_help_short),
646e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help(in_help),
647e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      is_target(in_is_target) {
648d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
649d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
650e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochFunctionInfo::FunctionInfo(NoBlockFunction nbf,
651e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help_short,
652e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const char* in_help,
653e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           bool in_is_target)
6543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
6553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
656a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
657a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(nbf),
658e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help_short(in_help_short),
659e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      help(in_help),
660e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      is_target(in_is_target) {
661d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
662d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
663a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Setup the function map via a static initializer. We use this because it
664a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// avoids race conditions without having to do some global setup function or
665a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// locking-heavy singleton checks at runtime. In practice, we always need this
666a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// before we can do anything interesting, so it's OK to wait for the
667a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// initializer.
668a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)struct FunctionInfoInitializer {
669a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoMap map;
670a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
671a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoInitializer() {
672e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    #define INSERT_FUNCTION(command, is_target) \
673e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        map[k##command] = FunctionInfo(&Run##command, \
674e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                       k##command##_HelpShort, \
675e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                       k##command##_Help, \
676e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                       is_target);
677e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
678e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Action, true)
679e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(ActionForEach, true)
680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INSERT_FUNCTION(Copy, true)
681e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Executable, true)
682e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Group, true)
683e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(SharedLibrary, true)
684e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(SourceSet, true)
685e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(StaticLibrary, true)
686e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
687e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Assert, false)
688e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Config, false)
689e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(DeclareArgs, false)
690e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Defined, false)
691e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(ExecScript, false)
692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INSERT_FUNCTION(ForEach, false)
693e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(GetEnv, false)
694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INSERT_FUNCTION(GetLabelInfo, false)
69546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    INSERT_FUNCTION(GetPathInfo, false)
696010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    INSERT_FUNCTION(GetTargetOutputs, false)
697e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Import, false)
698e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Print, false)
699e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(ProcessFileTemplate, false)
700e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(ReadFile, false)
701e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(RebasePath, false)
702e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(SetDefaults, false)
703e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(SetDefaultToolchain, false)
704e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(SetSourcesAssignmentFilter, false)
705e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Template, false)
706e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Tool, false)
707e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(Toolchain, false)
708e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(ToolchainArgs, false)
709e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INSERT_FUNCTION(WriteFile, false)
710a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
711a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    #undef INSERT_FUNCTION
712a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
713a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
714a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoInitializer function_info;
715d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
716a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoMap& GetFunctions() {
717a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return function_info.map;
718d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
719d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
720a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunFunction(Scope* scope,
721a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  const FunctionCallNode* function,
7223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  const ListNode* args_list,
723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  BlockNode* block,
724a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  Err* err) {
725d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Token& name = function->function();
726d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
727a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FunctionInfoMap& function_map = GetFunctions();
728a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoMap::const_iterator found_function =
729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      function_map.find(name.value());
730a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function == function_map.end()) {
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // No built-in function matching this, check for a template.
732effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const Template* templ =
733d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        scope->GetTemplate(function->function().value().as_string());
734effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (templ) {
7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Value args = args_list->Execute(scope, err);
7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (err->has_error())
7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return Value();
738effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return templ->Invoke(scope, function, args.list_value(), block, err);
7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
740d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
741a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(name, "Unknown function.");
742a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
743a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (found_function->second.self_evaluating_args_runner) {
7463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return found_function->second.self_evaluating_args_runner(
7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        scope, function, args_list, err);
7483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
7493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // All other function types take a pre-executed set of args.
7513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Value args = args_list->Execute(scope, err);
7523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err->has_error())
7533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
7543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
755a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function->second.generic_block_runner) {
756a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!block) {
757a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FillNeedsBlockError(function, err);
758a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return Value();
759a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
760a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return found_function->second.generic_block_runner(
7613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        scope, function, args.list_value(), block, err);
762a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
763a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
764a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function->second.executed_block_runner) {
765a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!block) {
766a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FillNeedsBlockError(function, err);
767a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return Value();
768a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
769d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
770d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    Scope block_scope(scope);
771d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    block->ExecuteBlockInScope(&block_scope, err);
772d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (err->has_error())
773d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return Value();
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Value result = found_function->second.executed_block_runner(
7763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        function, args.list_value(), &block_scope, err);
7771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (err->has_error())
7781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return Value();
7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!block_scope.CheckForUnusedVars(err))
7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return Value();
7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return result;
783d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
784d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
785a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Otherwise it's a no-block function.
7863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return found_function->second.no_block_runner(scope, function,
7873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                args.list_value(), err);
788d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
789a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
790a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace functions
791