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. Direct dependent configs from a breadth-first traversal of the\n" 201 " dependency 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, direct_dependent_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 " See \"gn help patterns\" for specifics on patterns.\n" 493 "\n" 494 " Typically this will be called once in the master build config script\n" 495 " to set up the filter for the current platform. Subsequent calls will\n" 496 " overwrite the previous values.\n" 497 "\n" 498 " If you want to bypass the filter and add a file even if it might\n" 499 " be filtered out, call set_sources_assignment_filter([]) to clear the\n" 500 " list of filters. This will apply until the current scope exits\n" 501 "\n" 502 "Example:\n" 503 " # Filter out all _win files.\n" 504 " set_sources_assignment_filter([ \"*_win.cc\", \"*_win.h\" ])\n"; 505 506 Value RunSetSourcesAssignmentFilter(Scope* scope, 507 const FunctionCallNode* function, 508 const std::vector<Value>& args, 509 Err* err) { 510 if (args.size() != 1) { 511 *err = Err(function, "set_sources_assignment_filter takes one argument."); 512 } else { 513 scoped_ptr<PatternList> f(new PatternList); 514 f->SetFromValue(args[0], err); 515 if (!err->has_error()) 516 scope->set_sources_assignment_filter(f.Pass()); 517 } 518 return Value(); 519 } 520 521 // print ----------------------------------------------------------------------- 522 523 const char kPrint[] = "print"; 524 const char kPrint_HelpShort[] = 525 "print: Prints to the console."; 526 const char kPrint_Help[] = 527 "print: Prints to the console.\n" 528 "\n" 529 " Prints all arguments to the console separated by spaces. A newline is\n" 530 " automatically appended to the end.\n" 531 "\n" 532 " This function is intended for debugging. Note that build files are run\n" 533 " in parallel so you may get interleaved prints. A buildfile may also\n" 534 " be executed more than once in parallel in the context of different\n" 535 " toolchains so the prints from one file may be duplicated or\n" 536 " interleaved with itself.\n" 537 "\n" 538 "Examples:\n" 539 " print(\"Hello world\")\n" 540 "\n" 541 " print(sources, deps)\n"; 542 543 Value RunPrint(Scope* scope, 544 const FunctionCallNode* function, 545 const std::vector<Value>& args, 546 Err* err) { 547 std::string output; 548 for (size_t i = 0; i < args.size(); i++) { 549 if (i != 0) 550 output.push_back(' '); 551 output.append(args[i].ToString(false)); 552 } 553 output.push_back('\n'); 554 555 const BuildSettings::PrintCallback& cb = 556 scope->settings()->build_settings()->print_callback(); 557 if (cb.is_null()) 558 printf("%s", output.c_str()); 559 else 560 cb.Run(output); 561 562 return Value(); 563 } 564 565 // ----------------------------------------------------------------------------- 566 567 FunctionInfo::FunctionInfo() 568 : self_evaluating_args_runner(NULL), 569 generic_block_runner(NULL), 570 executed_block_runner(NULL), 571 no_block_runner(NULL), 572 help_short(NULL), 573 help(NULL), 574 is_target(false) { 575 } 576 577 FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf, 578 const char* in_help_short, 579 const char* in_help, 580 bool in_is_target) 581 : self_evaluating_args_runner(seaf), 582 generic_block_runner(NULL), 583 executed_block_runner(NULL), 584 no_block_runner(NULL), 585 help_short(in_help_short), 586 help(in_help), 587 is_target(in_is_target) { 588 } 589 590 FunctionInfo::FunctionInfo(GenericBlockFunction gbf, 591 const char* in_help_short, 592 const char* in_help, 593 bool in_is_target) 594 : self_evaluating_args_runner(NULL), 595 generic_block_runner(gbf), 596 executed_block_runner(NULL), 597 no_block_runner(NULL), 598 help_short(in_help_short), 599 help(in_help), 600 is_target(in_is_target) { 601 } 602 603 FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, 604 const char* in_help_short, 605 const char* in_help, 606 bool in_is_target) 607 : self_evaluating_args_runner(NULL), 608 generic_block_runner(NULL), 609 executed_block_runner(ebf), 610 no_block_runner(NULL), 611 help_short(in_help_short), 612 help(in_help), 613 is_target(in_is_target) { 614 } 615 616 FunctionInfo::FunctionInfo(NoBlockFunction nbf, 617 const char* in_help_short, 618 const char* in_help, 619 bool in_is_target) 620 : self_evaluating_args_runner(NULL), 621 generic_block_runner(NULL), 622 executed_block_runner(NULL), 623 no_block_runner(nbf), 624 help_short(in_help_short), 625 help(in_help), 626 is_target(in_is_target) { 627 } 628 629 // Setup the function map via a static initializer. We use this because it 630 // avoids race conditions without having to do some global setup function or 631 // locking-heavy singleton checks at runtime. In practice, we always need this 632 // before we can do anything interesting, so it's OK to wait for the 633 // initializer. 634 struct FunctionInfoInitializer { 635 FunctionInfoMap map; 636 637 FunctionInfoInitializer() { 638 #define INSERT_FUNCTION(command, is_target) \ 639 map[k##command] = FunctionInfo(&Run##command, \ 640 k##command##_HelpShort, \ 641 k##command##_Help, \ 642 is_target); 643 644 INSERT_FUNCTION(Action, true) 645 INSERT_FUNCTION(ActionForEach, true) 646 INSERT_FUNCTION(Component, true) 647 INSERT_FUNCTION(Copy, true) 648 INSERT_FUNCTION(Executable, true) 649 INSERT_FUNCTION(Group, true) 650 INSERT_FUNCTION(SharedLibrary, true) 651 INSERT_FUNCTION(SourceSet, true) 652 INSERT_FUNCTION(StaticLibrary, true) 653 INSERT_FUNCTION(Test, true) 654 655 INSERT_FUNCTION(Assert, false) 656 INSERT_FUNCTION(Config, false) 657 INSERT_FUNCTION(DeclareArgs, false) 658 INSERT_FUNCTION(Defined, false) 659 INSERT_FUNCTION(ExecScript, false) 660 INSERT_FUNCTION(ForEach, false) 661 INSERT_FUNCTION(GetEnv, false) 662 INSERT_FUNCTION(GetLabelInfo, false) 663 INSERT_FUNCTION(GetPathInfo, false) 664 INSERT_FUNCTION(GetTargetOutputs, false) 665 INSERT_FUNCTION(Import, false) 666 INSERT_FUNCTION(Print, false) 667 INSERT_FUNCTION(ProcessFileTemplate, false) 668 INSERT_FUNCTION(ReadFile, false) 669 INSERT_FUNCTION(RebasePath, false) 670 INSERT_FUNCTION(SetDefaults, false) 671 INSERT_FUNCTION(SetDefaultToolchain, false) 672 INSERT_FUNCTION(SetSourcesAssignmentFilter, false) 673 INSERT_FUNCTION(Template, false) 674 INSERT_FUNCTION(Tool, false) 675 INSERT_FUNCTION(Toolchain, false) 676 INSERT_FUNCTION(ToolchainArgs, false) 677 INSERT_FUNCTION(WriteFile, false) 678 679 #undef INSERT_FUNCTION 680 } 681 }; 682 const FunctionInfoInitializer function_info; 683 684 const FunctionInfoMap& GetFunctions() { 685 return function_info.map; 686 } 687 688 Value RunFunction(Scope* scope, 689 const FunctionCallNode* function, 690 const ListNode* args_list, 691 BlockNode* block, 692 Err* err) { 693 const Token& name = function->function(); 694 695 const FunctionInfoMap& function_map = GetFunctions(); 696 FunctionInfoMap::const_iterator found_function = 697 function_map.find(name.value()); 698 if (found_function == function_map.end()) { 699 // No built-in function matching this, check for a template. 700 const Template* templ = 701 scope->GetTemplate(function->function().value().as_string()); 702 if (templ) { 703 Value args = args_list->Execute(scope, err); 704 if (err->has_error()) 705 return Value(); 706 return templ->Invoke(scope, function, args.list_value(), block, err); 707 } 708 709 *err = Err(name, "Unknown function."); 710 return Value(); 711 } 712 713 if (found_function->second.self_evaluating_args_runner) { 714 return found_function->second.self_evaluating_args_runner( 715 scope, function, args_list, err); 716 } 717 718 // All other function types take a pre-executed set of args. 719 Value args = args_list->Execute(scope, err); 720 if (err->has_error()) 721 return Value(); 722 723 if (found_function->second.generic_block_runner) { 724 if (!block) { 725 FillNeedsBlockError(function, err); 726 return Value(); 727 } 728 return found_function->second.generic_block_runner( 729 scope, function, args.list_value(), block, err); 730 } 731 732 if (found_function->second.executed_block_runner) { 733 if (!block) { 734 FillNeedsBlockError(function, err); 735 return Value(); 736 } 737 738 Scope block_scope(scope); 739 block->ExecuteBlockInScope(&block_scope, err); 740 if (err->has_error()) 741 return Value(); 742 return found_function->second.executed_block_runner( 743 function, args.list_value(), &block_scope, err); 744 } 745 746 // Otherwise it's a no-block function. 747 return found_function->second.no_block_runner(scope, function, 748 args.list_value(), err); 749 } 750 751 } // namespace functions 752