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