functions.cc revision d3868032626d59662ff73b372b5d584c1d144c53
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
31d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteAssert(const FunctionCallNode* function,
32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    const std::vector<Value>& args,
33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    Err* err) {
34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Wrong number of arguments.",
36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "assert() takes one argument, "
37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "were you expecting somethig else?");
38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else if (args[0].InterpretAsInt() == 0) {
39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Assertion failed.");
40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (args[0].origin()) {
41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // If you do "assert(foo)" we'd ideally like to show you where foo was
42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // set, and in this case the origin of the args will tell us that.
43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // However, if you do "assert(foo && bar)" the source of the value will
44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // be the assert like, which isn't so helpful.
45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      //
46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // So we try to see if the args are from the same line or not. This will
47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // break if you do "assert(\nfoo && bar)" and we may show the second line
48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // as the source, oh well. The way around this is to check to see if the
49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // origin node is inside our function call block.
50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      Location origin_location = args[0].origin()->GetRange().begin();
51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (origin_location.file() != function->function().location().file() ||
52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          origin_location.line_number() !=
53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch              function->function().location().line_number()) {
54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              "This is where it was set."));
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
62d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteConfig(Scope* scope,
63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    const FunctionCallNode* function,
64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    const std::vector<Value>& args,
65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    Err* err) {
66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Label label(MakeLabelForScope(scope, function, args[0].string_value()));
71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (g_scheduler->verbose_logging())
73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    g_scheduler->Log("Generating config", label.GetUserVisibleName(true));
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Create the empty config object.
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ItemTree* tree = &scope->settings()->build_settings()->item_tree();
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Config* config = Config::GetConfig(scope->settings(), function->GetRange(),
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                     label, NULL, err);
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Fill it.
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const SourceDir input_dir = SourceDirForFunctionCall(function);
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ConfigValuesGenerator gen(&config->config_values(), scope,
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            function->function(), input_dir, err);
86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  gen.Run();
87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Mark as complete.
91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  {
92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    base::AutoLock lock(tree->lock());
93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    tree->MarkItemGeneratedLocked(label);
94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
98d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteDeclareArgs(Scope* scope,
99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         const FunctionCallNode* function,
100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         const std::vector<Value>& args,
101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         Err* err) {
102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Only allow this to be called once. We use a variable in the current scope
103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // with a name the parser will reject if the user tried to type it.
104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const char did_declare_args_var[] = "@@declared_args";
105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (scope->GetValue(did_declare_args_var)) {
106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Duplicate call to declared_args.");
107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    err->AppendSubErr(
108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        Err(scope->GetValue(did_declare_args_var)->origin()->GetRange(),
109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            "See the original call."));
110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Find the root scope where the values will be set.
114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope* root = scope->mutable_containing();
115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!root || root->containing() || !scope->IsProcessingBuildConfig()) {
116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "declare_args called incorrectly."
117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "It must be called only from the build config script and in the "
118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "root scope.");
119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
122d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Take all variables set in the current scope as default values and put
123d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // them in the parent scope. The values in the current scope are the defaults,
124d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // then we apply the external args to this list.
125d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope::KeyValueVector values;
126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->GetCurrentScopeValues(&values);
127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (size_t i = 0; i < values.size(); i++) {
128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // TODO(brettw) actually import the arguments from the command line rather
129d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // than only using the defaults.
130d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    root->SetValue(values[i].first, values[i].second,
131d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                   values[i].second.origin());
132d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->SetValue(did_declare_args_var, Value(function, 1), NULL);
135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
138d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteImport(Scope* scope,
139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    const FunctionCallNode* function,
140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    const std::vector<Value>& args,
141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                    Err* err) {
142d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
143d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
144d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const SourceDir input_dir = SourceDirForFunctionCall(function);
147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  SourceFile import_file =
148d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      input_dir.ResolveRelativeFile(args[0].string_value());
149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->settings()->import_manager().DoImport(import_file, function,
150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                               scope, err);
151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
153d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
154d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteTemplate(Scope* scope,
155d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      const FunctionCallNode* invocation,
156d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      const std::vector<Value>& args,
157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      BlockNode* block,
158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      const FunctionCallNode* rule,
159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      Err* err) {
160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureNotProcessingImport(invocation, scope, err))
161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
162d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope block_scope(scope);
163d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!FillTargetBlockScope(scope, invocation,
164d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            invocation->function().value().data(),
165d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            block, args, &block_scope, err))
166d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
167d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
168d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Run the block for the rule invocation.
169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block->ExecuteBlockInScope(&block_scope, err);
170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
171d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Now run the rule itself with that block as the current scope.
174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  rule->block()->ExecuteBlockInScope(&block_scope, err);
175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
181d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteSetDefaults(Scope* scope,
182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         const FunctionCallNode* function,
183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         const std::vector<Value>& args,
184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         BlockNode* block,
185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                         Err* err) {
186d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err))
187d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
188d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const std::string& target_type(args[0].string_value());
189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Ensure there aren't defaults already set.
191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (scope->GetTargetDefaults(target_type)) {
192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(),
193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "This target type defaults were already set.");
194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Execute the block in a new scope that has a parent of the containing
198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // scope.
199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope block_scope(scope);
200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!FillTargetBlockScope(scope, function,
201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            function->function().value().data(),
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            block, args, &block_scope, err))
203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Run the block for the rule invocation.
206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block->ExecuteBlockInScope(&block_scope, err);
207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Now copy the values set on the scope we made into the free-floating one
211d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // (with no containing scope) used to hold the target defaults.
212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Scope* dest = scope->MakeTargetDefaults(target_type);
213d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err);
214d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
217d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteSetSourcesAssignmentFilter(Scope* scope,
218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                        const FunctionCallNode* function,
219d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                        const std::vector<Value>& args,
220d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                        Err* err) {
221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function, "set_sources_assignment_filter takes one argument.");
223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<PatternList> f(new PatternList);
225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    f->SetFromValue(args[0], err);
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!err->has_error())
227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      scope->set_sources_assignment_filter(f.Pass());
228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// void print(...)
233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// prints all arguments to the console separated by spaces.
234d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecutePrint(const std::vector<Value>& args, Err* err) {
235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (size_t i = 0; i < args.size(); i++) {
236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (i != 0)
237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      std::cout << " ";
238d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    std::cout << args[i].ToString();
239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::cout << std::endl;
241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace
245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// ----------------------------------------------------------------------------
247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace functions {
249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kAssert[] = "assert";
251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kComponent[] = "component";
252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kConfig[] = "config";
253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kCopy[] = "copy";
254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kCustom[] = "custom";
255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kDeclareArgs[] = "declare_args";
256d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kExecScript[] = "exec_script";
257d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kExecutable[] = "executable";
258d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kGroup[] = "group";
259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kImport[] = "import";
260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kPrint[] = "print";
261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kProcessFileTemplate[] = "process_file_template";
262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kReadFile[] = "read_file";
263d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kSetDefaults[] = "set_defaults";
264d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kSetDefaultToolchain[] = "set_default_toolchain";
265d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kSharedLibrary[] = "shared_library";
267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kStaticLibrary[] = "static_library";
268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kTemplate[] = "template";
269d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kTool[] = "tool";
270d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kToolchain[] = "toolchain";
271d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kTest[] = "test";
272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char kWriteFile[] = "write_file";
273d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
274d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace functions
275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
276d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// ----------------------------------------------------------------------------
277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EnsureNotProcessingImport(const ParseNode* node,
279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                               const Scope* scope,
280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                               Err* err) {
281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (scope->IsProcessingImport()) {
282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(node, "Not valid from an import.",
283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "We need to talk about this thing you are doing here. Doing this\n"
284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "kind of thing from an imported file makes me feel like you are\n"
285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "abusing me. Imports are for defining defaults, variables, and rules.\n"
286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "The appropriate place for this kind of thing is really in a normal\n"
287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "BUILD file.");
288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EnsureNotProcessingBuildConfig(const ParseNode* node,
294d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                    const Scope* scope,
295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                    Err* err) {
296d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (scope->IsProcessingBuildConfig()) {
297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(node, "Not valid from the build config.",
298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "You can't do this kind of thing from the build config script, "
299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        "silly!\nPut it in a regular BUILD file.");
300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
303d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
304d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
305d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool FillTargetBlockScope(const Scope* scope,
306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                          const FunctionCallNode* function,
307d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                          const char* target_type,
308d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                          const BlockNode* block,
309d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                          const std::vector<Value>& args,
310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                          Scope* block_scope,
311d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                          Err* err) {
312d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!block) {
313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    FillNeedsBlockError(function, err);
314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
315d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
316d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
317d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Copy the target defaults, if any, into the scope we're going to execute
318d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // the block in.
319d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Scope* default_scope = scope->GetTargetDefaults(target_type);
320d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (default_scope) {
321d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!default_scope->NonRecursiveMergeTo(block_scope, function,
322d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                            "target defaults", err))
323d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return false;
324d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
325d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
326d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // The name is the single argument to the target function.
327d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err))
328d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
329d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
330d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Set the target name variable to the current target, and mark it used
331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // because we don't want to issue an error if the script ignores it.
332d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const base::StringPiece target_name("target_name");
333d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block_scope->SetValue(target_name, Value(function, args[0].string_value()),
334d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                        function);
335d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  block_scope->MarkUsed(target_name);
336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return true;
337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
338d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
339d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool EnsureSingleStringArg(const FunctionCallNode* function,
340d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                           const std::vector<Value>& args,
341d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                           Err* err) {
342d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
343d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Incorrect arguments.",
344d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "This function requires a single string argument.");
345d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return false;
346d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
347d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return args[0].VerifyTypeIs(Value::STRING, err);
348d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
349d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
350d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function) {
351d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return function->function().location().file()->dir();
352d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
353d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
354d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst Label& ToolchainLabelForScope(const Scope* scope) {
355d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return scope->settings()->toolchain()->label();
356d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
357d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
358d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochLabel MakeLabelForScope(const Scope* scope,
359d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                        const FunctionCallNode* function,
360d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                        const std::string& name) {
361d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const SourceDir& input_dir = SourceDirForFunctionCall(function);
362d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Label& toolchain_label = ToolchainLabelForScope(scope);
363d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Label(input_dir, name, toolchain_label.dir(), toolchain_label.name());
364d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
365d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
366d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochValue ExecuteFunction(Scope* scope,
367d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      const FunctionCallNode* function,
368d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      const std::vector<Value>& args,
369d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      BlockNode* block,
370d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                      Err* err) {
371d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Token& name = function->function();
372d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (block) {
373d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // These target generators need to execute the block themselves.
374d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kComponent))
375d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteComponent(scope, function, args, block, err);
376d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kCustom))
377d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteCustom(scope, function, args, block, err);
378d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kExecutable))
379d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteExecutable(scope, function, args, block, err);
380d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kSetDefaults))
381d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteSetDefaults(scope, function, args, block, err);
382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kSharedLibrary))
383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteSharedLibrary(scope, function, args, block, err);
384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kStaticLibrary))
385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteStaticLibrary(scope, function, args, block, err);
386d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kGroup))
387d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteGroup(scope, function, args, block, err);
388d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kTest))
389d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteExecutable(scope, function, args, block, err);
390d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kTemplate))
391d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteTemplate(scope, function, args, block, err);
392d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kTool))
393d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteTool(scope, function, args, block, err);
394d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kToolchain))
395d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteToolchain(scope, function, args, block, err);
396d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const FunctionCallNode* rule =
398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        scope->GetTemplate(function->function().value().as_string());
399d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (rule)
400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteTemplate(scope, function, args, block, rule, err);
401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // FIXME(brettw) This is not right, what if you specify a function that
403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // doesn't take a block but specify one?!?!?
404d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
405d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // The rest of the functions can take a pre-executed block for simplicity.
406d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    Scope block_scope(scope);
407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    block->ExecuteBlockInScope(&block_scope, err);
408d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (err->has_error())
409d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return Value();
410d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
411d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kConfig))
412d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteConfig(&block_scope, function, args, err);
413d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kCopy))
414d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteCopy(&block_scope, function, args, err);
415d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (name.IsIdentifierEqualTo(functions::kDeclareArgs))
416d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return ExecuteDeclareArgs(&block_scope, function, args, err);
417d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
418d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(name, "Unknown function.");
419d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
420d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
421d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
422d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kAssert))
423d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteAssert(function, args, err);
424d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kExecScript))
425d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteExecScript(scope, function, args, err);
426d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kImport))
427d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteImport(scope, function, args, err);
428d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kPrint))
429d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecutePrint(args, err);
430d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kProcessFileTemplate))
431d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteProcessFileTemplate(scope, function, args, err);
432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kReadFile))
433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteReadFile(scope, function, args, err);
434d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kSetDefaultToolchain))
435d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteSetDefaultToolchain(scope, function, args, err);
436d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kSetSourcesAssignmentFilter))
437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteSetSourcesAssignmentFilter(scope, function, args, err);
438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (name.IsIdentifierEqualTo(functions::kWriteFile))
439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return ExecuteWriteFile(scope, function, args, err);
440d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
441d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  *err = Err(function, "Unknown function.");
442d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
443d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
444