Ninja
depfile_parser.cc
Go to the documentation of this file.
1 /* Generated by re2c 0.13.5 */
2 // Copyright 2011 Google Inc. All Rights Reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "depfile_parser.h"
17 
18 // A note on backslashes in Makefiles, from reading the docs:
19 // Backslash-newline is the line continuation character.
20 // Backslash-# escapes a # (otherwise meaningful as a comment start).
21 // Backslash-% escapes a % (otherwise meaningful as a special).
22 // Finally, quoting the GNU manual, "Backslashes that are not in danger
23 // of quoting ‘%’ characters go unmolested."
24 // How do you end a line with a backslash? The netbsd Make docs suggest
25 // reading the result of a shell command echoing a backslash!
26 //
27 // Rather than implement all of above, we do a simpler thing here:
28 // Backslashes escape a set of characters (see "escapes" defined below),
29 // otherwise they are passed through verbatim.
30 // If anyone actually has depfiles that rely on the more complicated
31 // behavior we can adjust this.
32 bool DepfileParser::Parse(string* content, string* err) {
33  // in: current parser input point.
34  // end: end of input.
35  // parsing_targets: whether we are parsing targets or dependencies.
36  char* in = &(*content)[0];
37  char* end = in + content->size();
38  bool parsing_targets = true;
39  while (in < end) {
40  // out: current output point (typically same as in, but can fall behind
41  // as we de-escape backslashes).
42  char* out = in;
43  // filename: start of the current parsed filename.
44  char* filename = out;
45  for (;;) {
46  // start: beginning of the current parsed span.
47  const char* start = in;
48 
49  {
50  char yych;
51  static const unsigned char yybm[] = {
52  0, 0, 0, 0, 0, 0, 0, 0,
53  0, 0, 0, 0, 0, 0, 0, 0,
54  0, 0, 0, 0, 0, 0, 0, 0,
55  0, 0, 0, 0, 0, 0, 0, 0,
56  0, 128, 0, 0, 0, 0, 0, 0,
57  128, 128, 0, 128, 128, 128, 128, 128,
58  128, 128, 128, 128, 128, 128, 128, 128,
59  128, 128, 128, 0, 0, 128, 0, 0,
60  128, 128, 128, 128, 128, 128, 128, 128,
61  128, 128, 128, 128, 128, 128, 128, 128,
62  128, 128, 128, 128, 128, 128, 128, 128,
63  128, 128, 128, 0, 0, 0, 0, 128,
64  0, 128, 128, 128, 128, 128, 128, 128,
65  128, 128, 128, 128, 128, 128, 128, 128,
66  128, 128, 128, 128, 128, 128, 128, 128,
67  128, 128, 128, 128, 0, 128, 128, 0,
68  0, 0, 0, 0, 0, 0, 0, 0,
69  0, 0, 0, 0, 0, 0, 0, 0,
70  0, 0, 0, 0, 0, 0, 0, 0,
71  0, 0, 0, 0, 0, 0, 0, 0,
72  0, 0, 0, 0, 0, 0, 0, 0,
73  0, 0, 0, 0, 0, 0, 0, 0,
74  0, 0, 0, 0, 0, 0, 0, 0,
75  0, 0, 0, 0, 0, 0, 0, 0,
76  0, 0, 0, 0, 0, 0, 0, 0,
77  0, 0, 0, 0, 0, 0, 0, 0,
78  0, 0, 0, 0, 0, 0, 0, 0,
79  0, 0, 0, 0, 0, 0, 0, 0,
80  0, 0, 0, 0, 0, 0, 0, 0,
81  0, 0, 0, 0, 0, 0, 0, 0,
82  0, 0, 0, 0, 0, 0, 0, 0,
83  0, 0, 0, 0, 0, 0, 0, 0,
84  };
85 
86  yych = *in;
87  if (yych <= '=') {
88  if (yych <= '$') {
89  if (yych <= ' ') {
90  if (yych <= 0x00) goto yy7;
91  goto yy9;
92  } else {
93  if (yych <= '!') goto yy5;
94  if (yych <= '#') goto yy9;
95  goto yy4;
96  }
97  } else {
98  if (yych <= '*') {
99  if (yych <= '\'') goto yy9;
100  if (yych <= ')') goto yy5;
101  goto yy9;
102  } else {
103  if (yych <= ':') goto yy5;
104  if (yych <= '<') goto yy9;
105  goto yy5;
106  }
107  }
108  } else {
109  if (yych <= '^') {
110  if (yych <= 'Z') {
111  if (yych <= '?') goto yy9;
112  goto yy5;
113  } else {
114  if (yych != '\\') goto yy9;
115  }
116  } else {
117  if (yych <= '{') {
118  if (yych == '`') goto yy9;
119  goto yy5;
120  } else {
121  if (yych <= '|') goto yy9;
122  if (yych <= '~') goto yy5;
123  goto yy9;
124  }
125  }
126  }
127  ++in;
128  if ((yych = *in) <= '"') {
129  if (yych <= '\f') {
130  if (yych <= 0x00) goto yy3;
131  if (yych != '\n') goto yy14;
132  } else {
133  if (yych <= '\r') goto yy3;
134  if (yych == ' ') goto yy16;
135  goto yy14;
136  }
137  } else {
138  if (yych <= 'Z') {
139  if (yych <= '#') goto yy16;
140  if (yych == '*') goto yy16;
141  goto yy14;
142  } else {
143  if (yych <= '\\') goto yy16;
144  if (yych == '|') goto yy16;
145  goto yy14;
146  }
147  }
148 yy3:
149  {
150  // For any other character (e.g. whitespace), swallow it here,
151  // allowing the outer logic to loop around again.
152  break;
153  }
154 yy4:
155  yych = *++in;
156  if (yych == '$') goto yy12;
157  goto yy3;
158 yy5:
159  ++in;
160  yych = *in;
161  goto yy11;
162 yy6:
163  {
164  // Got a span of plain text.
165  int len = (int)(in - start);
166  // Need to shift it over if we're overwriting backslashes.
167  if (out < start)
168  memmove(out, start, len);
169  out += len;
170  continue;
171  }
172 yy7:
173  ++in;
174  {
175  break;
176  }
177 yy9:
178  yych = *++in;
179  goto yy3;
180 yy10:
181  ++in;
182  yych = *in;
183 yy11:
184  if (yybm[0+yych] & 128) {
185  goto yy10;
186  }
187  goto yy6;
188 yy12:
189  ++in;
190  {
191  // De-escape dollar character.
192  *out++ = '$';
193  continue;
194  }
195 yy14:
196  ++in;
197  {
198  // Let backslash before other characters through verbatim.
199  *out++ = '\\';
200  *out++ = yych;
201  continue;
202  }
203 yy16:
204  ++in;
205  {
206  // De-escape backslashed character.
207  *out++ = yych;
208  continue;
209  }
210  }
211 
212  }
213 
214  int len = (int)(out - filename);
215  const bool is_target = parsing_targets;
216  if (len > 0 && filename[len - 1] == ':') {
217  len--; // Strip off trailing colon, if any.
218  parsing_targets = false;
219  }
220 
221  if (len == 0)
222  continue;
223 
224  if (!is_target) {
225  ins_.push_back(StringPiece(filename, len));
226  } else if (!out_.str_) {
227  out_ = StringPiece(filename, len);
228  } else if (out_ != StringPiece(filename, len)) {
229  *err = "depfile has multiple output paths";
230  return false;
231  }
232  }
233  return true;
234 }
const char * str_
Definition: string_piece.h:49
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:27
bool Parse(string *content, string *err)
Parse an input file.
vector< StringPiece > ins_
StringPiece out_