Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / tools / gn / functions.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "tools/gn/functions.h"
6
7 #include <iostream>
8
9 #include "base/environment.h"
10 #include "base/strings/string_util.h"
11 #include "tools/gn/config.h"
12 #include "tools/gn/config_values_generator.h"
13 #include "tools/gn/err.h"
14 #include "tools/gn/input_file.h"
15 #include "tools/gn/parse_tree.h"
16 #include "tools/gn/scheduler.h"
17 #include "tools/gn/scope.h"
18 #include "tools/gn/settings.h"
19 #include "tools/gn/template.h"
20 #include "tools/gn/token.h"
21 #include "tools/gn/value.h"
22
23 bool EnsureNotProcessingImport(const ParseNode* node,
24                                const Scope* scope,
25                                Err* err) {
26   if (scope->IsProcessingImport()) {
27     *err = Err(node, "Not valid from an import.",
28         "Imports are for defining defaults, variables, and rules. The\n"
29         "appropriate place for this kind of thing is really in a normal\n"
30         "BUILD file.");
31     return false;
32   }
33   return true;
34 }
35
36 bool EnsureNotProcessingBuildConfig(const ParseNode* node,
37                                     const Scope* scope,
38                                     Err* err) {
39   if (scope->IsProcessingBuildConfig()) {
40     *err = Err(node, "Not valid from the build config.",
41         "You can't do this kind of thing from the build config script, "
42         "silly!\nPut it in a regular BUILD file.");
43     return false;
44   }
45   return true;
46 }
47
48 bool FillTargetBlockScope(const Scope* scope,
49                           const FunctionCallNode* function,
50                           const std::string& target_type,
51                           const BlockNode* block,
52                           const std::vector<Value>& args,
53                           Scope* block_scope,
54                           Err* err) {
55   if (!block) {
56     FillNeedsBlockError(function, err);
57     return false;
58   }
59
60   // Copy the target defaults, if any, into the scope we're going to execute
61   // the block in.
62   const Scope* default_scope = scope->GetTargetDefaults(target_type);
63   if (default_scope) {
64     if (!default_scope->NonRecursiveMergeTo(block_scope, false, function,
65                                             "target defaults", err))
66       return false;
67   }
68
69   // The name is the single argument to the target function.
70   if (!EnsureSingleStringArg(function, args, err))
71     return false;
72
73   // Set the target name variable to the current target, and mark it used
74   // because we don't want to issue an error if the script ignores it.
75   const base::StringPiece target_name("target_name");
76   block_scope->SetValue(target_name, Value(function, args[0].string_value()),
77                         function);
78   block_scope->MarkUsed(target_name);
79   return true;
80 }
81
82 void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
83   *err = Err(function->function(), "This function call requires a block.",
84       "The block's \"{\" must be on the same line as the function "
85       "call's \")\".");
86 }
87
88 bool EnsureSingleStringArg(const FunctionCallNode* function,
89                            const std::vector<Value>& args,
90                            Err* err) {
91   if (args.size() != 1) {
92     *err = Err(function->function(), "Incorrect arguments.",
93                "This function requires a single string argument.");
94     return false;
95   }
96   return args[0].VerifyTypeIs(Value::STRING, err);
97 }
98
99 const Label& ToolchainLabelForScope(const Scope* scope) {
100   return scope->settings()->toolchain_label();
101 }
102
103 Label MakeLabelForScope(const Scope* scope,
104                         const FunctionCallNode* function,
105                         const std::string& name) {
106   const Label& toolchain_label = ToolchainLabelForScope(scope);
107   return Label(scope->GetSourceDir(), name, toolchain_label.dir(),
108                toolchain_label.name());
109 }
110
111 namespace functions {
112
113 // assert ----------------------------------------------------------------------
114
115 const char kAssert[] = "assert";
116 const char kAssert_HelpShort[] =
117     "assert: Assert an expression is true at generation time.";
118 const char kAssert_Help[] =
119     "assert: Assert an expression is true at generation time.\n"
120     "\n"
121     "  assert(<condition> [, <error string>])\n"
122     "\n"
123     "  If the condition is false, the build will fail with an error. If the\n"
124     "  optional second argument is provided, that string will be printed\n"
125     "  with the error message.\n"
126     "\n"
127     "Examples:\n"
128     "  assert(is_win)\n"
129     "  assert(defined(sources), \"Sources must be defined\")\n";
130
131 Value RunAssert(Scope* scope,
132                 const FunctionCallNode* function,
133                 const std::vector<Value>& args,
134                 Err* err) {
135   if (args.size() != 1 && args.size() != 2) {
136     *err = Err(function->function(), "Wrong number of arguments.",
137                "assert() takes one or two argument, "
138                "were you expecting somethig else?");
139   } else if (args[0].type() != Value::BOOLEAN) {
140     *err = Err(function->function(), "Assertion value not a bool.");
141   } else if (!args[0].boolean_value()) {
142     if (args.size() == 2) {
143       // Optional string message.
144       if (args[1].type() != Value::STRING) {
145         *err = Err(function->function(), "Assertion failed.",
146             "<<<ERROR MESSAGE IS NOT A STRING>>>");
147       } else {
148         *err = Err(function->function(), "Assertion failed.",
149             args[1].string_value());
150       }
151     } else {
152       *err = Err(function->function(), "Assertion failed.");
153     }
154
155     if (args[0].origin()) {
156       // If you do "assert(foo)" we'd ideally like to show you where foo was
157       // set, and in this case the origin of the args will tell us that.
158       // However, if you do "assert(foo && bar)" the source of the value will
159       // be the assert like, which isn't so helpful.
160       //
161       // So we try to see if the args are from the same line or not. This will
162       // break if you do "assert(\nfoo && bar)" and we may show the second line
163       // as the source, oh well. The way around this is to check to see if the
164       // origin node is inside our function call block.
165       Location origin_location = args[0].origin()->GetRange().begin();
166       if (origin_location.file() != function->function().location().file() ||
167           origin_location.line_number() !=
168               function->function().location().line_number()) {
169         err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
170                               "This is where it was set."));
171       }
172     }
173   }
174   return Value();
175 }
176
177 // config ----------------------------------------------------------------------
178
179 const char kConfig[] = "config";
180 const char kConfig_HelpShort[] =
181     "config: Defines a configuration object.";
182 const char kConfig_Help[] =
183     "config: Defines a configuration object.\n"
184     "\n"
185     "  Configuration objects can be applied to targets and specify sets of\n"
186     "  compiler flags, includes, defines, etc. They provide a way to\n"
187     "  conveniently group sets of this configuration information.\n"
188     "\n"
189     "  A config is referenced by its label just like a target.\n"
190     "\n"
191     "  The values in a config are additive only. If you want to remove a flag\n"
192     "  you need to remove the corresponding config that sets it. The final\n"
193     "  set of flags, defines, etc. for a target is generated in this order:\n"
194     "\n"
195     "   1. The values specified directly on the target (rather than using a\n"
196     "      config.\n"
197     "   2. The configs specified in the target's \"configs\" list, in order.\n"
198     "   3. Direct dependent configs from a breadth-first traversal of the\n"
199     "      dependency tree in the order that the targets appear in \"deps\".\n"
200     "   4. All dependent configs from a breadth-first traversal of the\n"
201     "      dependency tree in the order that the targets appear in \"deps\".\n"
202     "\n"
203     "Variables valid in a config definition:\n"
204     CONFIG_VALUES_VARS_HELP
205     "\n"
206     "Variables on a target used to apply configs:\n"
207     "  all_dependent_configs, configs, direct_dependent_configs,\n"
208     "  forward_dependent_configs_from\n"
209     "\n"
210     "Example:\n"
211     "  config(\"myconfig\") {\n"
212     "    includes = [ \"include/common\" ]\n"
213     "    defines = [ \"ENABLE_DOOM_MELON\" ]\n"
214     "  }\n"
215     "\n"
216     "  executable(\"mything\") {\n"
217     "    configs = [ \":myconfig\" ]\n"
218     "  }\n";
219
220 Value RunConfig(const FunctionCallNode* function,
221                 const std::vector<Value>& args,
222                 Scope* scope,
223                 Err* err) {
224   if (!EnsureSingleStringArg(function, args, err) ||
225       !EnsureNotProcessingImport(function, scope, err))
226     return Value();
227
228   Label label(MakeLabelForScope(scope, function, args[0].string_value()));
229
230   if (g_scheduler->verbose_logging())
231     g_scheduler->Log("Defining config", label.GetUserVisibleName(true));
232
233   // Create the new config.
234   scoped_ptr<Config> config(new Config(scope->settings(), label));
235   config->set_defined_from(function);
236   if (!Visibility::FillItemVisibility(config.get(), scope, err))
237     return Value();
238
239   // Fill it.
240   const SourceDir& input_dir = scope->GetSourceDir();
241   ConfigValuesGenerator gen(&config->config_values(), scope, input_dir, err);
242   gen.Run();
243   if (err->has_error())
244     return Value();
245
246   // Save the generated item.
247   Scope::ItemVector* collector = scope->GetItemCollector();
248   if (!collector) {
249     *err = Err(function, "Can't define a config in this context.");
250     return Value();
251   }
252   collector->push_back(new scoped_ptr<Item>(config.PassAs<Item>()));
253
254   return Value();
255 }
256
257 // declare_args ----------------------------------------------------------------
258
259 const char kDeclareArgs[] = "declare_args";
260 const char kDeclareArgs_HelpShort[] =
261     "declare_args: Declare build arguments.";
262 const char kDeclareArgs_Help[] =
263     "declare_args: Declare build arguments.\n"
264     "\n"
265     "  Introduces the given arguments into the current scope. If they are\n"
266     "  not specified on the command line or in a toolchain's arguments,\n"
267     "  the default values given in the declare_args block will be used.\n"
268     "  However, these defaults will not override command-line values.\n"
269     "\n"
270     "  See also \"gn help buildargs\" for an overview.\n"
271     "\n"
272     "Example:\n"
273     "  declare_args() {\n"
274     "    enable_teleporter = true\n"
275     "    enable_doom_melon = false\n"
276     "  }\n"
277     "\n"
278     "  If you want to override the (default disabled) Doom Melon:\n"
279     "    gn --args=\"enable_doom_melon=true enable_teleporter=false\"\n"
280     "  This also sets the teleporter, but it's already defaulted to on so\n"
281     "  it will have no effect.\n";
282
283 Value RunDeclareArgs(Scope* scope,
284                      const FunctionCallNode* function,
285                      const std::vector<Value>& args,
286                      BlockNode* block,
287                      Err* err) {
288   Scope block_scope(scope);
289   block->ExecuteBlockInScope(&block_scope, err);
290   if (err->has_error())
291     return Value();
292
293   // Pass the values from our scope into the Args object for adding to the
294   // scope with the proper values (taking into account the defaults given in
295   // the block_scope, and arguments passed into the build).
296   Scope::KeyValueMap values;
297   block_scope.GetCurrentScopeValues(&values);
298   scope->settings()->build_settings()->build_args().DeclareArgs(
299       values, scope, err);
300   return Value();
301 }
302
303 // defined ---------------------------------------------------------------------
304
305 const char kDefined[] = "defined";
306 const char kDefined_HelpShort[] =
307     "defined: Returns whether an identifier is defined.";
308 const char kDefined_Help[] =
309     "defined: Returns whether an identifier is defined.\n"
310     "\n"
311     "  Returns true if the given argument is defined. This is most useful in\n"
312     "  templates to assert that the caller set things up properly.\n"
313     "\n"
314     "  You can pass an identifier:\n"
315     "    defined(foo)\n"
316     "  which will return true or false depending on whether foo is defined in\n"
317     "  the current scope.\n"
318     "\n"
319     "  You can also check a named scope:\n"
320     "    defined(foo.bar)\n"
321     "  which returns true if both foo is defined and bar is defined on the\n"
322     "  named scope foo. It will throw an error if foo is defined but is not\n"
323     "  a scope.\n"
324     "\n"
325     "Example:\n"
326     "\n"
327     "  template(\"mytemplate\") {\n"
328     "    # To help users call this template properly...\n"
329     "    assert(defined(invoker.sources), \"Sources must be defined\")\n"
330     "\n"
331     "    # If we want to accept an optional \"values\" argument, we don't\n"
332     "    # want to dereference something that may not be defined.\n"
333     "    if (defined(invoker.values)) {\n"
334     "      values = invoker.values\n"
335     "    } else {\n"
336     "      values = \"some default value\"\n"
337     "    }\n"
338     "  }\n";
339
340 Value RunDefined(Scope* scope,
341                  const FunctionCallNode* function,
342                  const ListNode* args_list,
343                  Err* err) {
344   const std::vector<const ParseNode*>& args_vector = args_list->contents();
345   if (args_vector.size() != 1) {
346     *err = Err(function, "Wrong number of arguments to defined().",
347                "Expecting exactly one.");
348     return Value();
349   }
350
351   const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
352   if (identifier) {
353     // Passed an identifier "defined(foo)".
354     if (scope->GetValue(identifier->value().value()))
355       return Value(function, true);
356     return Value(function, false);
357   }
358
359   const AccessorNode* accessor = args_vector[0]->AsAccessor();
360   if (accessor) {
361     // Passed an accessor "defined(foo.bar)".
362     if (accessor->member()) {
363       // The base of the accessor must be a scope if it's defined.
364       const Value* base = scope->GetValue(accessor->base().value());
365       if (!base)
366         return Value(function, false);
367       if (!base->VerifyTypeIs(Value::SCOPE, err))
368         return Value();
369
370       // Check the member inside the scope to see if its defined.
371       if (base->scope_value()->GetValue(accessor->member()->value().value()))
372         return Value(function, true);
373       return Value(function, false);
374     }
375   }
376
377   // Argument is invalid.
378   *err = Err(function, "Bad thing passed to defined().",
379       "It should be of the form defined(foo) or defined(foo.bar).");
380   return Value();
381 }
382
383 // getenv ----------------------------------------------------------------------
384
385 const char kGetEnv[] = "getenv";
386 const char kGetEnv_HelpShort[] =
387     "getenv: Get an environment variable.";
388 const char kGetEnv_Help[] =
389     "getenv: Get an environment variable.\n"
390     "\n"
391     "  value = getenv(env_var_name)\n"
392     "\n"
393     "  Returns the value of the given enironment variable. If the value is\n"
394     "  not found, it will try to look up the variable with the \"opposite\"\n"
395     "  case (based on the case of the first letter of the variable), but\n"
396     "  is otherwise case-sensitive.\n"
397     "\n"
398     "  If the environment variable is not found, the empty string will be\n"
399     "  returned. Note: it might be nice to extend this if we had the concept\n"
400     "  of \"none\" in the language to indicate lookup failure.\n"
401     "\n"
402     "Example:\n"
403     "\n"
404     "  home_dir = getenv(\"HOME\")\n";
405
406 Value RunGetEnv(Scope* scope,
407                 const FunctionCallNode* function,
408                 const std::vector<Value>& args,
409                 Err* err) {
410   if (!EnsureSingleStringArg(function, args, err))
411     return Value();
412
413   scoped_ptr<base::Environment> env(base::Environment::Create());
414
415   std::string result;
416   if (!env->GetVar(args[0].string_value().c_str(), &result))
417     return Value(function, "");  // Not found, return empty string.
418   return Value(function, result);
419 }
420
421 // import ----------------------------------------------------------------------
422
423 const char kImport[] = "import";
424 const char kImport_HelpShort[] =
425     "import: Import a file into the current scope.";
426 const char kImport_Help[] =
427     "import: Import a file into the current scope.\n"
428     "\n"
429     "  The import command loads the rules and variables resulting from\n"
430     "  executing the given file into the current scope.\n"
431     "\n"
432     "  By convention, imported files are named with a .gni extension.\n"
433     "\n"
434     "  An import is different than a C++ \"include\". The imported file is\n"
435     "  executed in a standalone environment from the caller of the import\n"
436     "  command. The results of this execution are cached for other files that\n"
437     "  import the same .gni file.\n"
438     "\n"
439     "  Note that you can not import a BUILD.gn file that's otherwise used\n"
440     "  in the build. Files must either be imported or implicitly loaded as\n"
441     "  a result of deps rules, but not both.\n"
442     "\n"
443     "  The imported file's scope will be merged with the scope at the point\n"
444     "  import was called. If there is a conflict (both the current scope and\n"
445     "  the imported file define some variable or rule with the same name but\n"
446     "  different value), a runtime error will be thrown. Therefore, it's good\n"
447     "  practice to minimize the stuff that an imported file defines.\n"
448     "\n"
449     "Examples:\n"
450     "\n"
451     "  import(\"//build/rules/idl_compilation_rule.gni\")\n"
452     "\n"
453     "  # Looks in the current directory.\n"
454     "  import(\"my_vars.gni\")\n";
455
456 Value RunImport(Scope* scope,
457                 const FunctionCallNode* function,
458                 const std::vector<Value>& args,
459                 Err* err) {
460   if (!EnsureSingleStringArg(function, args, err))
461     return Value();
462
463   const SourceDir& input_dir = scope->GetSourceDir();
464   SourceFile import_file =
465       input_dir.ResolveRelativeFile(args[0].string_value());
466   scope->settings()->import_manager().DoImport(import_file, function,
467                                                scope, err);
468   return Value();
469 }
470
471 // set_sources_assignment_filter -----------------------------------------------
472
473 const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
474 const char kSetSourcesAssignmentFilter_HelpShort[] =
475     "set_sources_assignment_filter: Set a pattern to filter source files.";
476 const char kSetSourcesAssignmentFilter_Help[] =
477     "set_sources_assignment_filter: Set a pattern to filter source files.\n"
478     "\n"
479     "  The sources assignment filter is a list of patterns that remove files\n"
480     "  from the list implicitly whenever the \"sources\" variable is\n"
481     "  assigned to. This is intended to be used to globally filter out files\n"
482     "  with platform-specific naming schemes when they don't apply, for\n"
483     "  example, you may want to filter out all \"*_win.cc\" files on non-\n"
484     "  Windows platforms.\n"
485     "\n"
486     "  See \"gn help patterns\" for specifics on patterns.\n"
487     "\n"
488     "  Typically this will be called once in the master build config script\n"
489     "  to set up the filter for the current platform. Subsequent calls will\n"
490     "  overwrite the previous values.\n"
491     "\n"
492     "  If you want to bypass the filter and add a file even if it might\n"
493     "  be filtered out, call set_sources_assignment_filter([]) to clear the\n"
494     "  list of filters. This will apply until the current scope exits\n"
495     "\n"
496     "Example:\n"
497     "  # Filter out all _win files.\n"
498     "  set_sources_assignment_filter([ \"*_win.cc\", \"*_win.h\" ])\n";
499
500 Value RunSetSourcesAssignmentFilter(Scope* scope,
501                                     const FunctionCallNode* function,
502                                     const std::vector<Value>& args,
503                                     Err* err) {
504   if (args.size() != 1) {
505     *err = Err(function, "set_sources_assignment_filter takes one argument.");
506   } else {
507     scoped_ptr<PatternList> f(new PatternList);
508     f->SetFromValue(args[0], err);
509     if (!err->has_error())
510       scope->set_sources_assignment_filter(f.Pass());
511   }
512   return Value();
513 }
514
515 // print -----------------------------------------------------------------------
516
517 const char kPrint[] = "print";
518 const char kPrint_HelpShort[] =
519     "print: Prints to the console.";
520 const char kPrint_Help[] =
521     "print: Prints to the console.\n"
522     "\n"
523     "  Prints all arguments to the console separated by spaces. A newline is\n"
524     "  automatically appended to the end.\n"
525     "\n"
526     "  This function is intended for debugging. Note that build files are run\n"
527     "  in parallel so you may get interleaved prints. A buildfile may also\n"
528     "  be executed more than once in parallel in the context of different\n"
529     "  toolchains so the prints from one file may be duplicated or\n"
530     "  interleaved with itself.\n"
531     "\n"
532     "Examples:\n"
533     "  print(\"Hello world\")\n"
534     "\n"
535     "  print(sources, deps)\n";
536
537 Value RunPrint(Scope* scope,
538                const FunctionCallNode* function,
539                const std::vector<Value>& args,
540                Err* err) {
541   std::string output;
542   for (size_t i = 0; i < args.size(); i++) {
543     if (i != 0)
544       output.push_back(' ');
545     output.append(args[i].ToString(false));
546   }
547   output.push_back('\n');
548
549   const BuildSettings::PrintCallback& cb =
550       scope->settings()->build_settings()->print_callback();
551   if (cb.is_null())
552     printf("%s", output.c_str());
553   else
554     cb.Run(output);
555
556   return Value();
557 }
558
559 // -----------------------------------------------------------------------------
560
561 FunctionInfo::FunctionInfo()
562     : self_evaluating_args_runner(NULL),
563       generic_block_runner(NULL),
564       executed_block_runner(NULL),
565       no_block_runner(NULL),
566       help_short(NULL),
567       help(NULL),
568       is_target(false) {
569 }
570
571 FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf,
572                            const char* in_help_short,
573                            const char* in_help,
574                            bool in_is_target)
575     : self_evaluating_args_runner(seaf),
576       generic_block_runner(NULL),
577       executed_block_runner(NULL),
578       no_block_runner(NULL),
579       help_short(in_help_short),
580       help(in_help),
581       is_target(in_is_target) {
582 }
583
584 FunctionInfo::FunctionInfo(GenericBlockFunction gbf,
585                            const char* in_help_short,
586                            const char* in_help,
587                            bool in_is_target)
588     : self_evaluating_args_runner(NULL),
589       generic_block_runner(gbf),
590       executed_block_runner(NULL),
591       no_block_runner(NULL),
592       help_short(in_help_short),
593       help(in_help),
594       is_target(in_is_target) {
595 }
596
597 FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf,
598                            const char* in_help_short,
599                            const char* in_help,
600                            bool in_is_target)
601     : self_evaluating_args_runner(NULL),
602       generic_block_runner(NULL),
603       executed_block_runner(ebf),
604       no_block_runner(NULL),
605       help_short(in_help_short),
606       help(in_help),
607       is_target(in_is_target) {
608 }
609
610 FunctionInfo::FunctionInfo(NoBlockFunction nbf,
611                            const char* in_help_short,
612                            const char* in_help,
613                            bool in_is_target)
614     : self_evaluating_args_runner(NULL),
615       generic_block_runner(NULL),
616       executed_block_runner(NULL),
617       no_block_runner(nbf),
618       help_short(in_help_short),
619       help(in_help),
620       is_target(in_is_target) {
621 }
622
623 // Setup the function map via a static initializer. We use this because it
624 // avoids race conditions without having to do some global setup function or
625 // locking-heavy singleton checks at runtime. In practice, we always need this
626 // before we can do anything interesting, so it's OK to wait for the
627 // initializer.
628 struct FunctionInfoInitializer {
629   FunctionInfoMap map;
630
631   FunctionInfoInitializer() {
632     #define INSERT_FUNCTION(command, is_target) \
633         map[k##command] = FunctionInfo(&Run##command, \
634                                        k##command##_HelpShort, \
635                                        k##command##_Help, \
636                                        is_target);
637
638     INSERT_FUNCTION(Action, true)
639     INSERT_FUNCTION(ActionForEach, true)
640     INSERT_FUNCTION(Component, true)
641     INSERT_FUNCTION(Executable, true)
642     INSERT_FUNCTION(Group, true)
643     INSERT_FUNCTION(SharedLibrary, true)
644     INSERT_FUNCTION(SourceSet, true)
645     INSERT_FUNCTION(StaticLibrary, true)
646     INSERT_FUNCTION(Test, true)
647
648     INSERT_FUNCTION(Assert, false)
649     INSERT_FUNCTION(Config, false)
650     INSERT_FUNCTION(Copy, false)
651     INSERT_FUNCTION(DeclareArgs, false)
652     INSERT_FUNCTION(Defined, false)
653     INSERT_FUNCTION(ExecScript, false)
654     INSERT_FUNCTION(GetEnv, false)
655     INSERT_FUNCTION(GetTargetOutputs, false)
656     INSERT_FUNCTION(Import, false)
657     INSERT_FUNCTION(Print, false)
658     INSERT_FUNCTION(ProcessFileTemplate, false)
659     INSERT_FUNCTION(ReadFile, false)
660     INSERT_FUNCTION(RebasePath, false)
661     INSERT_FUNCTION(SetDefaults, false)
662     INSERT_FUNCTION(SetDefaultToolchain, false)
663     INSERT_FUNCTION(SetSourcesAssignmentFilter, false)
664     INSERT_FUNCTION(Template, false)
665     INSERT_FUNCTION(Tool, false)
666     INSERT_FUNCTION(Toolchain, false)
667     INSERT_FUNCTION(ToolchainArgs, false)
668     INSERT_FUNCTION(WriteFile, false)
669
670     #undef INSERT_FUNCTION
671   }
672 };
673 const FunctionInfoInitializer function_info;
674
675 const FunctionInfoMap& GetFunctions() {
676   return function_info.map;
677 }
678
679 Value RunFunction(Scope* scope,
680                   const FunctionCallNode* function,
681                   const ListNode* args_list,
682                   BlockNode* block,
683                   Err* err) {
684   const Token& name = function->function();
685
686   const FunctionInfoMap& function_map = GetFunctions();
687   FunctionInfoMap::const_iterator found_function =
688       function_map.find(name.value());
689   if (found_function == function_map.end()) {
690     // No built-in function matching this, check for a template.
691     const Template* templ =
692         scope->GetTemplate(function->function().value().as_string());
693     if (templ) {
694       Value args = args_list->Execute(scope, err);
695       if (err->has_error())
696         return Value();
697       return templ->Invoke(scope, function, args.list_value(), block, err);
698     }
699
700     *err = Err(name, "Unknown function.");
701     return Value();
702   }
703
704   if (found_function->second.self_evaluating_args_runner) {
705     return found_function->second.self_evaluating_args_runner(
706         scope, function, args_list, err);
707   }
708
709   // All other function types take a pre-executed set of args.
710   Value args = args_list->Execute(scope, err);
711   if (err->has_error())
712     return Value();
713
714   if (found_function->second.generic_block_runner) {
715     if (!block) {
716       FillNeedsBlockError(function, err);
717       return Value();
718     }
719     return found_function->second.generic_block_runner(
720         scope, function, args.list_value(), block, err);
721   }
722
723   if (found_function->second.executed_block_runner) {
724     if (!block) {
725       FillNeedsBlockError(function, err);
726       return Value();
727     }
728
729     Scope block_scope(scope);
730     block->ExecuteBlockInScope(&block_scope, err);
731     if (err->has_error())
732       return Value();
733     return found_function->second.executed_block_runner(
734         function, args.list_value(), &block_scope, err);
735   }
736
737   // Otherwise it's a no-block function.
738   return found_function->second.no_block_runner(scope, function,
739                                                 args.list_value(), err);
740 }
741
742 }  // namespace functions