diff options
-rw-r--r-- | misc/ninja_syntax.py | 35 | ||||
-rw-r--r-- | misc/zsh-completion | 47 | ||||
-rw-r--r-- | src/depfile_parser.cc | 20 | ||||
-rw-r--r-- | src/depfile_parser.in.cc | 6 | ||||
-rw-r--r-- | src/depfile_parser_test.cc | 19 | ||||
-rw-r--r-- | src/ninja.cc | 2 |
6 files changed, 94 insertions, 35 deletions
diff --git a/misc/ninja_syntax.py b/misc/ninja_syntax.py index 4b9b547..14b932f 100644 --- a/misc/ninja_syntax.py +++ b/misc/ninja_syntax.py @@ -8,10 +8,9 @@ use Python. """ import textwrap -import re def escape_path(word): - return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:') + return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') class Writer(object): def __init__(self, output, width=78): @@ -74,7 +73,7 @@ class Writer(object): all_inputs.extend(order_only) self._line('build %s: %s' % (' '.join(out_outputs), - ' '.join([rule] + all_inputs))) + ' '.join([rule] + all_inputs))) if variables: if isinstance(variables, dict): @@ -97,13 +96,13 @@ class Writer(object): self._line('default %s' % ' '.join(self._as_list(paths))) def _count_dollars_before_index(self, s, i): - """Returns the number of '$' characters right in front of s[i].""" - dollar_count = 0 - dollar_index = i - 1 - while dollar_index > 0 and s[dollar_index] == '$': - dollar_count += 1 - dollar_index -= 1 - return dollar_count + """Returns the number of '$' characters right in front of s[i].""" + dollar_count = 0 + dollar_index = i - 1 + while dollar_index > 0 and s[dollar_index] == '$': + dollar_count += 1 + dollar_index -= 1 + return dollar_count def _line(self, text, indent=0): """Write 'text' word-wrapped at self.width characters.""" @@ -116,19 +115,19 @@ class Writer(object): available_space = self.width - len(leading_space) - len(' $') space = available_space while True: - space = text.rfind(' ', 0, space) - if space < 0 or \ - self._count_dollars_before_index(text, space) % 2 == 0: - break + space = text.rfind(' ', 0, space) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break if space < 0: # No such space; just use the first unescaped space we can find. space = available_space - 1 while True: - space = text.find(' ', space + 1) - if space < 0 or \ - self._count_dollars_before_index(text, space) % 2 == 0: - break + space = text.find(' ', space + 1) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break if space < 0: # Give up on breaking. break diff --git a/misc/zsh-completion b/misc/zsh-completion index cd0edfb..2fe16fb 100644 --- a/misc/zsh-completion +++ b/misc/zsh-completion @@ -1,3 +1,4 @@ +#compdef ninja # Copyright 2011 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +16,47 @@ # Add the following to your .zshrc to tab-complete ninja targets # . path/to/ninja/misc/zsh-completion -_ninja() { - reply=(`(ninja -t targets all 2&>/dev/null) | awk -F: '{print $1}'`) +__get_targets() { + ninja -t targets 2>/dev/null | while read -r a b; do echo $a | cut -d ':' -f1; done; } -compctl -K _ninja ninja + +__get_tools() { + ninja -t list 2>/dev/null | while read -r a b; do echo $a; done | tail -n +2 +} + +__get_modes() { + ninja -d list 2>/dev/null | while read -r a b; do echo $a; done | tail -n +2 | head -n -1 +} + +__modes() { + local -a modes + modes=(${(fo)"$(__get_modes)"}) + _describe 'modes' modes +} + +__tools() { + local -a tools + tools=(${(fo)"$(__get_tools)"}) + _describe 'tools' tools +} + +__targets() { + local -a targets + targets=(${(fo)"$(__get_targets)"}) + _describe 'targets' targets +} + +_arguments \ + {-h,--help}'[Show help]' \ + '--version[Print ninja version]' \ + '-C+[Change to directory before doing anything else]:directories:_directories' \ + '-f+[Specify input build file (default=build.ninja)]:files:_files' \ + '-j+[Run N jobs in parallel (default=number of CPUs available)]:number of jobs' \ + '-l+[Do not start new jobs if the load average is greater than N]:number of jobs' \ + '-k+[Keep going until N jobs fail (default=1)]:number of jobs' \ + '-n[Dry run (do not run commands but act like they succeeded)]' \ + '-v[Show all command lines while building]' \ + '-d+[Enable debugging (use -d list to list modes)]:modes:__modes' \ + '-t+[Run a subtool (use -t list to list subtools)]:tools:__tools' \ + '*::targets:__targets' + diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc index 49c7d7b..4ca3943 100644 --- a/src/depfile_parser.cc +++ b/src/depfile_parser.cc @@ -64,7 +64,7 @@ bool DepfileParser::Parse(string* content, string* err) { 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 0, 0, 0, 128, 0, + 128, 128, 128, 128, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -114,27 +114,29 @@ bool DepfileParser::Parse(string* content, string* err) { if (yych != '\\') goto yy9; } } else { - if (yych <= 'z') { + if (yych <= '{') { if (yych == '`') goto yy9; goto yy5; } else { - if (yych == '~') goto yy5; + if (yych <= '|') goto yy9; + if (yych <= '~') goto yy5; goto yy9; } } } ++in; - if ((yych = *in) <= '#') { - if (yych <= '\n') { + if ((yych = *in) <= '"') { + if (yych <= '\f') { if (yych <= 0x00) goto yy3; - if (yych <= '\t') goto yy14; + if (yych != '\n') goto yy14; } else { + if (yych <= '\r') goto yy3; if (yych == ' ') goto yy16; - if (yych <= '"') goto yy14; - goto yy16; + goto yy14; } } else { if (yych <= 'Z') { + if (yych <= '#') goto yy16; if (yych == '*') goto yy16; goto yy14; } else { @@ -224,7 +226,7 @@ yy16: } else if (!out_.str_) { out_ = StringPiece(filename, len); } else if (out_ != StringPiece(filename, len)) { - *err = "depfile has multiple output paths."; + *err = "depfile has multiple output paths"; return false; } } diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc index 8bb6d84..b59baf0 100644 --- a/src/depfile_parser.in.cc +++ b/src/depfile_parser.in.cc @@ -67,13 +67,13 @@ bool DepfileParser::Parse(string* content, string* err) { *out++ = '$'; continue; } - '\\' [^\000\n] { + '\\' [^\000\r\n] { // Let backslash before other characters through verbatim. *out++ = '\\'; *out++ = yych; continue; } - [a-zA-Z0-9+,/_:.~()@=!-]+ { + [a-zA-Z0-9+,/_:.~()}{@=!-]+ { // Got a span of plain text. int len = (int)(in - start); // Need to shift it over if we're overwriting backslashes. @@ -108,7 +108,7 @@ bool DepfileParser::Parse(string* content, string* err) { } else if (!out_.str_) { out_ = StringPiece(filename, len); } else if (out_ != StringPiece(filename, len)) { - *err = "depfile has multiple output paths."; + *err = "depfile has multiple output paths"; return false; } } diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc index 0f6771a..a5f3321 100644 --- a/src/depfile_parser_test.cc +++ b/src/depfile_parser_test.cc @@ -58,6 +58,17 @@ TEST_F(DepfileParserTest, Continuation) { EXPECT_EQ(2u, parser_.ins_.size()); } +TEST_F(DepfileParserTest, CarriageReturnContinuation) { + string err; + EXPECT_TRUE(Parse( +"foo.o: \\\r\n" +" bar.h baz.h\r\n", + &err)); + ASSERT_EQ("", err); + EXPECT_EQ("foo.o", parser_.out_.AsString()); + EXPECT_EQ(2u, parser_.ins_.size()); +} + TEST_F(DepfileParserTest, BackSlashes) { string err; EXPECT_TRUE(Parse( @@ -109,16 +120,19 @@ TEST_F(DepfileParserTest, SpecialChars) { string err; EXPECT_TRUE(Parse( "C:/Program\\ Files\\ (x86)/Microsoft\\ crtdefs.h: \n" -" en@quot.header~ t+t-x!=1", +" en@quot.header~ t+t-x!=1 \n" +" openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif", &err)); ASSERT_EQ("", err); EXPECT_EQ("C:/Program Files (x86)/Microsoft crtdefs.h", parser_.out_.AsString()); - ASSERT_EQ(2u, parser_.ins_.size()); + ASSERT_EQ(3u, parser_.ins_.size()); EXPECT_EQ("en@quot.header~", parser_.ins_[0].AsString()); EXPECT_EQ("t+t-x!=1", parser_.ins_[1].AsString()); + EXPECT_EQ("openldap/slapd.d/cn=config/cn=schema/cn={0}core.ldif", + parser_.ins_[2].AsString()); } TEST_F(DepfileParserTest, UnifyMultipleOutputs) { @@ -136,4 +150,5 @@ TEST_F(DepfileParserTest, RejectMultipleDifferentOutputs) { // check that multiple different outputs are rejected by the parser string err; EXPECT_FALSE(Parse("foo bar: x y z", &err)); + ASSERT_EQ("depfile has multiple output paths", err); } diff --git a/src/ninja.cc b/src/ninja.cc index 03ca83b..50de43e 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -631,6 +631,8 @@ int NinjaMain::ToolCompilationDatabase(int argc, char* argv[]) { putchar('['); for (vector<Edge*>::iterator e = state_.edges_.begin(); e != state_.edges_.end(); ++e) { + if ((*e)->inputs_.empty()) + continue; for (int i = 0; i != argc; ++i) { if ((*e)->rule_->name() == argv[i]) { if (!first) |