1 /* Generated by re2c 0.13.5 */
\r
2 // Copyright 2011 Google Inc. All Rights Reserved.
\r
4 // Licensed under the Apache License, Version 2.0 (the "License");
\r
5 // you may not use this file except in compliance with the License.
\r
6 // You may obtain a copy of the License at
\r
8 // http://www.apache.org/licenses/LICENSE-2.0
\r
10 // Unless required by applicable law or agreed to in writing, software
\r
11 // distributed under the License is distributed on an "AS IS" BASIS,
\r
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 // See the License for the specific language governing permissions and
\r
14 // limitations under the License.
\r
16 #include "depfile_parser.h"
\r
18 // A note on backslashes in Makefiles, from reading the docs:
\r
19 // Backslash-newline is the line continuation character.
\r
20 // Backslash-# escapes a # (otherwise meaningful as a comment start).
\r
21 // Backslash-% escapes a % (otherwise meaningful as a special).
\r
22 // Finally, quoting the GNU manual, "Backslashes that are not in danger
\r
23 // of quoting ‘%’ characters go unmolested."
\r
24 // How do you end a line with a backslash? The netbsd Make docs suggest
\r
25 // reading the result of a shell command echoing a backslash!
\r
27 // Rather than implement all of above, we do a simpler thing here:
\r
28 // Backslashes escape a set of characters (see "escapes" defined below),
\r
29 // otherwise they are passed through verbatim.
\r
30 // If anyone actually has depfiles that rely on the more complicated
\r
31 // behavior we can adjust this.
\r
32 bool DepfileParser::Parse(string* content, string* err) {
\r
33 // in: current parser input point.
\r
34 // end: end of input.
\r
35 // parsing_targets: whether we are parsing targets or dependencies.
\r
36 char* in = &(*content)[0];
\r
37 char* end = in + content->size();
\r
38 bool parsing_targets = true;
\r
40 // out: current output point (typically same as in, but can fall behind
\r
41 // as we de-escape backslashes).
\r
43 // filename: start of the current parsed filename.
\r
44 char* filename = out;
\r
46 // start: beginning of the current parsed span.
\r
47 const char* start = in;
\r
51 static const unsigned char yybm[] = {
\r
52 0, 0, 0, 0, 0, 0, 0, 0,
\r
53 0, 0, 0, 0, 0, 0, 0, 0,
\r
54 0, 0, 0, 0, 0, 0, 0, 0,
\r
55 0, 0, 0, 0, 0, 0, 0, 0,
\r
56 0, 128, 0, 0, 0, 0, 0, 0,
\r
57 128, 128, 0, 128, 128, 128, 128, 128,
\r
58 128, 128, 128, 128, 128, 128, 128, 128,
\r
59 128, 128, 128, 0, 0, 128, 0, 0,
\r
60 128, 128, 128, 128, 128, 128, 128, 128,
\r
61 128, 128, 128, 128, 128, 128, 128, 128,
\r
62 128, 128, 128, 128, 128, 128, 128, 128,
\r
63 128, 128, 128, 0, 0, 0, 0, 128,
\r
64 0, 128, 128, 128, 128, 128, 128, 128,
\r
65 128, 128, 128, 128, 128, 128, 128, 128,
\r
66 128, 128, 128, 128, 128, 128, 128, 128,
\r
67 128, 128, 128, 128, 0, 128, 128, 0,
\r
68 0, 0, 0, 0, 0, 0, 0, 0,
\r
69 0, 0, 0, 0, 0, 0, 0, 0,
\r
70 0, 0, 0, 0, 0, 0, 0, 0,
\r
71 0, 0, 0, 0, 0, 0, 0, 0,
\r
72 0, 0, 0, 0, 0, 0, 0, 0,
\r
73 0, 0, 0, 0, 0, 0, 0, 0,
\r
74 0, 0, 0, 0, 0, 0, 0, 0,
\r
75 0, 0, 0, 0, 0, 0, 0, 0,
\r
76 0, 0, 0, 0, 0, 0, 0, 0,
\r
77 0, 0, 0, 0, 0, 0, 0, 0,
\r
78 0, 0, 0, 0, 0, 0, 0, 0,
\r
79 0, 0, 0, 0, 0, 0, 0, 0,
\r
80 0, 0, 0, 0, 0, 0, 0, 0,
\r
81 0, 0, 0, 0, 0, 0, 0, 0,
\r
82 0, 0, 0, 0, 0, 0, 0, 0,
\r
83 0, 0, 0, 0, 0, 0, 0, 0,
\r
90 if (yych <= 0x00) goto yy7;
\r
93 if (yych <= '!') goto yy5;
\r
94 if (yych <= '#') goto yy9;
\r
99 if (yych <= '\'') goto yy9;
\r
100 if (yych <= ')') goto yy5;
\r
103 if (yych <= ':') goto yy5;
\r
104 if (yych <= '<') goto yy9;
\r
111 if (yych <= '?') goto yy9;
\r
114 if (yych != '\\') goto yy9;
\r
118 if (yych == '`') goto yy9;
\r
121 if (yych <= '|') goto yy9;
\r
122 if (yych <= '~') goto yy5;
\r
128 if ((yych = *in) <= '"') {
\r
129 if (yych <= '\f') {
\r
130 if (yych <= 0x00) goto yy3;
\r
131 if (yych != '\n') goto yy14;
\r
133 if (yych <= '\r') goto yy3;
\r
134 if (yych == ' ') goto yy16;
\r
139 if (yych <= '#') goto yy16;
\r
140 if (yych == '*') goto yy16;
\r
143 if (yych <= '\\') goto yy16;
\r
144 if (yych == '|') goto yy16;
\r
150 // For any other character (e.g. whitespace), swallow it here,
\r
151 // allowing the outer logic to loop around again.
\r
156 if (yych == '$') goto yy12;
\r
164 // Got a span of plain text.
\r
165 int len = (int)(in - start);
\r
166 // Need to shift it over if we're overwriting backslashes.
\r
168 memmove(out, start, len);
\r
184 if (yybm[0+yych] & 128) {
\r
191 // De-escape dollar character.
\r
198 // Let backslash before other characters through verbatim.
\r
206 // De-escape backslashed character.
\r
214 int len = (int)(out - filename);
\r
215 const bool is_target = parsing_targets;
\r
216 if (len > 0 && filename[len - 1] == ':') {
\r
217 len--; // Strip off trailing colon, if any.
\r
218 parsing_targets = false;
\r
225 ins_.push_back(StringPiece(filename, len));
\r
226 } else if (!out_.str_) {
\r
227 out_ = StringPiece(filename, len);
\r
228 } else if (out_ != StringPiece(filename, len)) {
\r
229 *err = "depfile has multiple output paths";
\r
233 if (parsing_targets) {
\r
234 *err = "expected ':' in depfile";
\r