functions.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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
9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_util.h"
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config_values_generator.h"
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/input_file.h"
14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/item_tree.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"
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target_manager.h"
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/token.h"
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/value.h"
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace {
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  *err = Err(function->function(), "This function call requires a block.",
27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      "The block's \"{\" must be on the same line as the function "
28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      "call's \")\".");
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This is called when a template is invoked. When we see a template
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declaration, that funciton is RunTemplate.
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunTemplateInvocation(Scope* scope,
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const FunctionCallNode* invocation,
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const std::vector<Value>& args,
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            BlockNode* block,
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const FunctionCallNode* rule,
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            Err* err) {
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!EnsureNotProcessingImport(invocation, scope, err))
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Scope block_scope(scope);
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!FillTargetBlockScope(scope, invocation,
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            invocation->function().value().data(),
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            block, args, &block_scope, err))
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run the block for the rule invocation.
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block->ExecuteBlockInScope(&block_scope, err);
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (err->has_error())
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Now run the rule itself with that block as the current scope.
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  rule->block()->ExecuteBlockInScope(&block_scope, err);
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (err->has_error())
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return Value();
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// ----------------------------------------------------------------------------
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingImport(const ParseNode* node,
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               const Scope* scope,
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               Err* err) {
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (scope->IsProcessingImport()) {
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(node, "Not valid from an import.",
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "We need to talk about this thing you are doing here. Doing this\n"
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "kind of thing from an imported file makes me feel like you are\n"
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "abusing me. Imports are for defining defaults, variables, and rules.\n"
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "The appropriate place for this kind of thing is really in a normal\n"
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "BUILD file.");
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingBuildConfig(const ParseNode* node,
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const Scope* scope,
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    Err* err) {
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (scope->IsProcessingBuildConfig()) {
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(node, "Not valid from the build config.",
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "You can't do this kind of thing from the build config script, "
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "silly!\nPut it in a regular BUILD file.");
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool FillTargetBlockScope(const Scope* scope,
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const FunctionCallNode* function,
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const char* target_type,
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const BlockNode* block,
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const std::vector<Value>& args,
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          Scope* block_scope,
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          Err* err) {
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!block) {
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    FillNeedsBlockError(function, err);
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Copy the target defaults, if any, into the scope we're going to execute
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the block in.
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Scope* default_scope = scope->GetTargetDefaults(target_type);
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (default_scope) {
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!default_scope->NonRecursiveMergeTo(block_scope, function,
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            "target defaults", err))
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return false;
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The name is the single argument to the target function.
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!EnsureSingleStringArg(function, args, err))
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Set the target name variable to the current target, and mark it used
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // because we don't want to issue an error if the script ignores it.
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const base::StringPiece target_name("target_name");
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block_scope->SetValue(target_name, Value(function, args[0].string_value()),
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        function);
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block_scope->MarkUsed(target_name);
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureSingleStringArg(const FunctionCallNode* function,
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           const std::vector<Value>& args,
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           Err* err) {
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (args.size() != 1) {
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(function->function(), "Incorrect arguments.",
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               "This function requires a single string argument.");
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return args[0].VerifyTypeIs(Value::STRING, err);
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function) {
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return function->function().location().file()->dir();
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const Label& ToolchainLabelForScope(const Scope* scope) {
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return scope->settings()->toolchain()->label();
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Label MakeLabelForScope(const Scope* scope,
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const FunctionCallNode* function,
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const std::string& name) {
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const SourceDir& input_dir = SourceDirForFunctionCall(function);
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Label& toolchain_label = ToolchainLabelForScope(scope);
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return Label(input_dir, name, toolchain_label.dir(), toolchain_label.name());
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace functions {
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// assert ----------------------------------------------------------------------
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert[] = "assert";
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert_Help[] =
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) WRITE ME";
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunAssert(Scope* scope,
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const FunctionCallNode* function,
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Wrong number of arguments.",
166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "assert() takes one argument, "
167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "were you expecting somethig else?");
168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else if (args[0].InterpretAsInt() == 0) {
169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Assertion failed.");
170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (args[0].origin()) {
171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // If you do "assert(foo)" we'd ideally like to show you where foo was
172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // set, and in this case the origin of the args will tell us that.
173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // However, if you do "assert(foo && bar)" the source of the value will
174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // be the assert like, which isn't so helpful.
175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      //
176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // So we try to see if the args are from the same line or not. This will
177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // break if you do "assert(\nfoo && bar)" and we may show the second line
178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // as the source, oh well. The way around this is to check to see if the
179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // origin node is inside our function call block.
180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      Location origin_location = args[0].origin()->GetRange().begin();
181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (origin_location.file() != function->function().location().file() ||
182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          origin_location.line_number() !=
183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch              function->function().location().line_number()) {
184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              "This is where it was set."));
186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// config ----------------------------------------------------------------------
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig[] = "config";
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig_Help[] =
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunConfig(const FunctionCallNode* function,
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Scope* scope,
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Label label(MakeLabelForScope(scope, function, args[0].string_value()));
207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (g_scheduler->verbose_logging())
209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    g_scheduler->Log("Generating config", label.GetUserVisibleName(true));
210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Create the empty config object.
212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ItemTree* tree = &scope->settings()->build_settings()->item_tree();
213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Config* config = Config::GetConfig(scope->settings(), function->GetRange(),
214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                     label, NULL, err);
215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
217d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Fill it.
219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const SourceDir input_dir = SourceDirForFunctionCall(function);
220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ConfigValuesGenerator gen(&config->config_values(), scope,
221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            function->function(), input_dir, err);
222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  gen.Run();
223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Mark as complete.
227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  {
228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    base::AutoLock lock(tree->lock());
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tree->MarkItemDefinedLocked(scope->settings()->build_settings(), label,
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                err);
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declare_args ----------------------------------------------------------------
236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs[] = "declare_args";
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs_Help[] =
239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunDeclareArgs(const FunctionCallNode* function,
242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     const std::vector<Value>& args,
243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     Scope* scope,
244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     Err* err) {
245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Only allow this to be called once. We use a variable in the current scope
246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // with a name the parser will reject if the user tried to type it.
247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const char did_declare_args_var[] = "@@declared_args";
248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (scope->GetValue(did_declare_args_var)) {
249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Duplicate call to declared_args.");
250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    err->AppendSubErr(
251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        Err(scope->GetValue(did_declare_args_var)->origin()->GetRange(),
252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            "See the original call."));
253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Find the root scope where the values will be set.
257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope* root = scope->mutable_containing();
258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!root || root->containing() || !scope->IsProcessingBuildConfig()) {
259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "declare_args called incorrectly."
260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "It must be called only from the build config script and in the "
261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "root scope.");
262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Take all variables set in the current scope as default values and put
266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // them in the parent scope. The values in the current scope are the defaults,
267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // then we apply the external args to this list.
268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope::KeyValueVector values;
269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->GetCurrentScopeValues(&values);
270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (size_t i = 0; i < values.size(); i++) {
271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // TODO(brettw) actually import the arguments from the command line rather
272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // than only using the defaults.
273d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    root->SetValue(values[i].first, values[i].second,
274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                   values[i].second.origin());
275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->SetValue(did_declare_args_var, Value(function, 1), NULL);
278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// import ----------------------------------------------------------------------
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport[] = "import";
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport_Help[] =
285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "import: Import a file into the current scope.\n"
286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  The import command loads the rules and variables resulting from\n"
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  executing the given file into the current scope.\n"
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  By convention, imported files are named with a .gni extension.\n"
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  It does not do an \"include\". The imported file is executed in a\n"
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  standalone environment from the caller of the import command. The\n"
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  results of this execution are cached for other files that import the\n"
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  same .gni file.\n"
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  Note that you can not import a BUILD.gn file that's otherwise used\n"
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  in the build. Files must either be imported or implicitly loaded as\n"
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  a result of deps rules, but not both.\n"
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  The imported file's scope will be merged with the scope at the point\n"
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import was called. If there is a conflict (both the current scope and\n"
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  the imported file define some variable or rule with the same name)\n"
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  a runtime error will be thrown. Therefore, it's good practice to\n"
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  minimize the stuff that an imported file defines.\n"
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "Examples:\n"
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import(\"//build/rules/idl_compilation_rule.gni\")\n"
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  # Looks in the current directory.\n"
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import(\"my_vars.gni\")\n";
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunImport(Scope* scope,
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const FunctionCallNode* function,
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
318d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
319d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
320d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
321d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
322d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const SourceDir input_dir = SourceDirForFunctionCall(function);
323d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  SourceFile import_file =
324d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      input_dir.ResolveRelativeFile(args[0].string_value());
325d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->settings()->import_manager().DoImport(import_file, function,
326d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                               scope, err);
327d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
328d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
329d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// set_defaults ----------------------------------------------------------------
331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetDefaults[] = "set_defaults";
333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetDefaults_Help[] =
334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunSetDefaults(Scope* scope,
337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     const FunctionCallNode* function,
338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     const std::vector<Value>& args,
339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     BlockNode* block,
340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     Err* err) {
341d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err))
342d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
343d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const std::string& target_type(args[0].string_value());
344d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
345d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Ensure there aren't defaults already set.
346d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (scope->GetTargetDefaults(target_type)) {
347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(),
348d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "This target type defaults were already set.");
349d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
350d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Execute the block in a new scope that has a parent of the containing
353d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // scope.
354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope block_scope(scope);
355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!FillTargetBlockScope(scope, function,
356d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            function->function().value().data(),
357d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            block, args, &block_scope, err))
358d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
359d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
360d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Run the block for the rule invocation.
361d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block->ExecuteBlockInScope(&block_scope, err);
362d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
363d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
364d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
365d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Now copy the values set on the scope we made into the free-floating one
366d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // (with no containing scope) used to hold the target defaults.
367d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope* dest = scope->MakeTargetDefaults(target_type);
368d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err);
369d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
370d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
371d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// set_sources_assignment_filter -----------------------------------------------
373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter_Help[] =
376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunSetSourcesAssignmentFilter(Scope* scope,
379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const FunctionCallNode* function,
380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const std::vector<Value>& args,
381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    Err* err) {
382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function, "set_sources_assignment_filter takes one argument.");
384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<PatternList> f(new PatternList);
386d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    f->SetFromValue(args[0], err);
387d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!err->has_error())
388d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      scope->set_sources_assignment_filter(f.Pass());
389d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
390d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
391d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
392d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// print -----------------------------------------------------------------------
394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint[] = "print";
396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint_Help[] =
397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "print(...)\n"
398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  Prints all arguments to the console separated by spaces. A newline is\n"
399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  automatically appended to the end.\n"
400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  This function is intended for debugging. Note that build files are run\n"
402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  in parallel so you may get interleaved prints. A buildfile may also\n"
403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  be executed more than once in parallel in the context of different\n"
404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  toolchains so the prints from one file may be duplicated or\n"
405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  interleaved with itself.\n"
406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
407a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "Examples:\n"
408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  print(\"Hello world\")\n"
409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  print(sources, deps)\n";
411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunPrint(Scope* scope,
413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               const FunctionCallNode* function,
414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               const std::vector<Value>& args,
415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               Err* err) {
416d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (size_t i = 0; i < args.size(); i++) {
417d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (i != 0)
418d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      std::cout << " ";
419d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    std::cout << args[i].ToString();
420d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
421d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::cout << std::endl;
422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// -----------------------------------------------------------------------------
426d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo()
428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : generic_block_runner(NULL),
429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(NULL) {
432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help)
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : generic_block_runner(gbf),
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(in_help) {
439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
440d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help)
442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : generic_block_runner(NULL),
443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(ebf),
444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(in_help) {
446d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
447d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help)
449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : generic_block_runner(NULL),
450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(nbf),
452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(in_help) {
453d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
454d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Setup the function map via a static initializer. We use this because it
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// avoids race conditions without having to do some global setup function or
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// locking-heavy singleton checks at runtime. In practice, we always need this
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// before we can do anything interesting, so it's OK to wait for the
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// initializer.
460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)struct FunctionInfoInitializer {
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoMap map;
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoInitializer() {
464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    #define INSERT_FUNCTION(command) \
465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        map[k##command] = FunctionInfo(&Run##command, k##command##_Help);
466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Assert)
468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Component)
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Config)
470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Copy)
471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Custom)
472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(DeclareArgs)
473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(ExecScript)
474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Executable)
475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Group)
476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Import)
477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Print)
478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(ProcessFileTemplate)
479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(ReadFile)
480a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SetDefaults)
481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SetDefaultToolchain)
482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SetSourcesAssignmentFilter)
483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SharedLibrary)
484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(StaticLibrary)
485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Template)
486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Test)
487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Tool)
488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Toolchain)
489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(WriteFile)
490a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    #undef INSERT_FUNCTION
492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoInitializer function_info;
495d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoMap& GetFunctions() {
497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return function_info.map;
498d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
499d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunFunction(Scope* scope,
501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  const FunctionCallNode* function,
502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  const std::vector<Value>& args,
503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  BlockNode* block,
504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  Err* err) {
505d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Token& name = function->function();
506d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FunctionInfoMap& function_map = GetFunctions();
508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoMap::const_iterator found_function =
509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      function_map.find(name.value());
510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function == function_map.end()) {
511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // No build-in function matching this, check for a template.
512d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const FunctionCallNode* rule =
513d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        scope->GetTemplate(function->function().value().as_string());
514d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (rule)
515a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return RunTemplateInvocation(scope, function, args, block, rule, err);
516d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(name, "Unknown function.");
518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function->second.generic_block_runner) {
522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!block) {
523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FillNeedsBlockError(function, err);
524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return Value();
525a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return found_function->second.generic_block_runner(
527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        scope, function, args, block, err);
528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function->second.executed_block_runner) {
531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!block) {
532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FillNeedsBlockError(function, err);
533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return Value();
534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
535d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
536d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    Scope block_scope(scope);
537d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    block->ExecuteBlockInScope(&block_scope, err);
538d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (err->has_error())
539d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return Value();
540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return found_function->second.executed_block_runner(
541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        function, args, &block_scope, err);
542d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
543d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Otherwise it's a no-block function.
545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return found_function->second.no_block_runner(scope, function, args, err);
546d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
547a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace functions
549