Replace command buffer FlushSync with WaitForTokenInRange and WaitForGetOffsetInRange
[chromium-blink-merge.git] / tools / gn / command_args.cc
blob72a623f219cacf52d28fd2b06c23887275b31e16
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.
5 #include <map>
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "tools/gn/commands.h"
10 #include "tools/gn/input_file.h"
11 #include "tools/gn/parse_tree.h"
12 #include "tools/gn/setup.h"
13 #include "tools/gn/standard_out.h"
14 #include "tools/gn/tokenizer.h"
16 namespace commands {
18 namespace {
20 bool DoesLineBeginWithComment(const base::StringPiece& line) {
21 // Skip whitespace.
22 size_t i = 0;
23 while (i < line.size() && IsAsciiWhitespace(line[i]))
24 i++;
26 return i < line.size() && line[i] == '#';
29 // Returns the offset of the beginning of the line identified by |offset|.
30 size_t BackUpToLineBegin(const std::string& data, size_t offset) {
31 // Degenerate case of an empty line. Below we'll try to return the
32 // character after the newline, but that will be incorrect in this case.
33 if (offset == 0 || Tokenizer::IsNewline(data, offset))
34 return offset;
36 size_t cur = offset;
37 do {
38 cur --;
39 if (Tokenizer::IsNewline(data, cur))
40 return cur + 1; // Want the first character *after* the newline.
41 } while (cur > 0);
42 return 0;
45 // Assumes DoesLineBeginWithComment(), this strips the # character from the
46 // beginning and normalizes preceeding whitespace.
47 std::string StripHashFromLine(const base::StringPiece& line) {
48 // Replace the # sign and everything before it with 3 spaces, so that a
49 // normal comment that has a space after the # will be indented 4 spaces
50 // (which makes our formatting come out nicely). If the comment is indented
51 // from there, we want to preserve that indenting.
52 return " " + line.substr(line.find('#') + 1).as_string();
55 // Tries to find the comment before the setting of the given value.
56 void GetContextForValue(const Value& value,
57 std::string* location_str,
58 std::string* comment) {
59 Location location = value.origin()->GetRange().begin();
60 const InputFile* file = location.file();
61 if (!file)
62 return;
64 *location_str = file->name().value() + ":" +
65 base::IntToString(location.line_number());
67 const std::string& data = file->contents();
68 size_t line_off =
69 Tokenizer::ByteOffsetOfNthLine(data, location.line_number());
71 while (line_off > 1) {
72 line_off -= 2; // Back up to end of previous line.
73 size_t previous_line_offset = BackUpToLineBegin(data, line_off);
75 base::StringPiece line(&data[previous_line_offset],
76 line_off - previous_line_offset + 1);
77 if (!DoesLineBeginWithComment(line))
78 break;
80 comment->insert(0, StripHashFromLine(line) + "\n");
81 line_off = previous_line_offset;
85 void PrintArgHelp(const base::StringPiece& name, const Value& value) {
86 OutputString(name.as_string(), DECORATION_YELLOW);
87 OutputString(" Default = " + value.ToString(true) + "\n");
89 if (value.origin()) {
90 std::string location, comment;
91 GetContextForValue(value, &location, &comment);
92 OutputString(" " + location + "\n" + comment);
93 } else {
94 OutputString(" (Internally set)\n");
98 } // namespace
100 extern const char kArgs[] = "args";
101 extern const char kArgs_HelpShort[] =
102 "args: Display configurable arguments declared by the build.";
103 extern const char kArgs_Help[] =
104 "gn args [arg name]\n"
105 " Displays all arguments declared by buildfiles along with their\n"
106 " description. Build arguments are anything in a declare_args() block\n"
107 " in any buildfile. The comment preceding the declaration will be\n"
108 " displayed here (so comment well!).\n"
109 "\n"
110 " These arguments can be overridden on the command-line:\n"
111 " --args=\"doom_melon_setting=5 component_build=1\"\n"
112 " or in a toolchain definition (see \"gn help buildargs\" for more on\n"
113 " how this all works).\n"
114 "\n"
115 " If \"arg name\" is specified, only the information for that argument\n"
116 " will be displayed. Otherwise all arguments will be displayed.\n";
118 int RunArgs(const std::vector<std::string>& args) {
119 Setup* setup = new Setup;
120 setup->set_check_for_bad_items(false);
121 // TODO(brettw) bug 343726: Use a temporary directory instead of this
122 // default one to avoid messing up any build that's in there.
123 if (!setup->DoSetup("//out/Default/") || !setup->Run())
124 return 1;
126 Scope::KeyValueMap build_args;
127 setup->build_settings().build_args().MergeDeclaredArguments(&build_args);
129 if (args.size() == 1) {
130 // Get help on a specific command.
131 Scope::KeyValueMap::const_iterator found_arg = build_args.find(args[0]);
132 if (found_arg == build_args.end()) {
133 Err(Location(), "Unknown build argument.",
134 "You asked for \"" + args[0] + "\" which I didn't find in any "
135 "buildfile\nassociated with this build.");
136 return 1;
138 PrintArgHelp(args[0], found_arg->second);
139 return 0;
140 } else if (args.size() > 1) {
141 // Too many arguments.
142 Err(Location(), "You're holding it wrong.",
143 "Usage: \"gn args [arg name]\"").PrintToStdout();
144 return 1;
147 // List all arguments. First put them in a regular map so they're sorted.
148 std::map<base::StringPiece, Value> sorted_args;
149 for (Scope::KeyValueMap::const_iterator i = build_args.begin();
150 i != build_args.end(); ++i)
151 sorted_args.insert(*i);
153 OutputString(
154 "Available build arguments. Note that the which arguments are declared\n"
155 "and their default values may depend on other arguments or the current\n"
156 "platform and architecture. So setting some values may add, remove, or\n"
157 "change the default value of other values.\n\n");
159 for (std::map<base::StringPiece, Value>::iterator i = sorted_args.begin();
160 i != sorted_args.end(); ++i) {
161 PrintArgHelp(i->first, i->second);
162 OutputString("\n");
165 return 0;
168 } // namespace commands