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