Imported Upstream version 1.7.1
[platform/upstream/ninja.git] / src / depfile_parser.cc
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       unsigned 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         128, 128, 128, 128, 128, 128, 128, 128, 
69         128, 128, 128, 128, 128, 128, 128, 128, 
70         128, 128, 128, 128, 128, 128, 128, 128, 
71         128, 128, 128, 128, 128, 128, 128, 128, 
72         128, 128, 128, 128, 128, 128, 128, 128, 
73         128, 128, 128, 128, 128, 128, 128, 128, 
74         128, 128, 128, 128, 128, 128, 128, 128, 
75         128, 128, 128, 128, 128, 128, 128, 128, 
76         128, 128, 128, 128, 128, 128, 128, 128, 
77         128, 128, 128, 128, 128, 128, 128, 128, 
78         128, 128, 128, 128, 128, 128, 128, 128, 
79         128, 128, 128, 128, 128, 128, 128, 128, 
80         128, 128, 128, 128, 128, 128, 128, 128, 
81         128, 128, 128, 128, 128, 128, 128, 128, 
82         128, 128, 128, 128, 128, 128, 128, 128, 
83         128, 128, 128, 128, 128, 128, 128, 128, 
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 <= '[') {
111             if (yych <= '?') goto yy9;
112             if (yych <= 'Z') goto yy5;
113             goto yy9;
114           } else {
115             if (yych <= '\\') goto yy2;
116             if (yych <= '^') goto yy9;
117             goto yy5;
118           }
119         } else {
120           if (yych <= '|') {
121             if (yych <= '`') goto yy9;
122             if (yych <= '{') goto yy5;
123             goto yy9;
124           } else {
125             if (yych == 0x7F) goto yy9;
126             goto yy5;
127           }
128         }
129       }
130 yy2:
131       ++in;
132       if ((yych = *in) <= '"') {
133         if (yych <= '\f') {
134           if (yych <= 0x00) goto yy3;
135           if (yych != '\n') goto yy14;
136         } else {
137           if (yych <= '\r') goto yy3;
138           if (yych == ' ') goto yy16;
139           goto yy14;
140         }
141       } else {
142         if (yych <= 'Z') {
143           if (yych <= '#') goto yy16;
144           if (yych == '*') goto yy16;
145           goto yy14;
146         } else {
147           if (yych <= '\\') goto yy16;
148           if (yych == '|') goto yy16;
149           goto yy14;
150         }
151       }
152 yy3:
153       {
154         // For any other character (e.g. whitespace), swallow it here,
155         // allowing the outer logic to loop around again.
156         break;
157       }
158 yy4:
159       yych = *++in;
160       if (yych == '$') goto yy12;
161       goto yy3;
162 yy5:
163       ++in;
164       yych = *in;
165       goto yy11;
166 yy6:
167       {
168         // Got a span of plain text.
169         int len = (int)(in - start);
170         // Need to shift it over if we're overwriting backslashes.
171         if (out < start)
172           memmove(out, start, len);
173         out += len;
174         continue;
175       }
176 yy7:
177       ++in;
178       {
179         break;
180       }
181 yy9:
182       yych = *++in;
183       goto yy3;
184 yy10:
185       ++in;
186       yych = *in;
187 yy11:
188       if (yybm[0+yych] & 128) {
189         goto yy10;
190       }
191       goto yy6;
192 yy12:
193       ++in;
194       {
195         // De-escape dollar character.
196         *out++ = '$';
197         continue;
198       }
199 yy14:
200       ++in;
201       {
202         // Let backslash before other characters through verbatim.
203         *out++ = '\\';
204         *out++ = yych;
205         continue;
206       }
207 yy16:
208       ++in;
209       {
210         // De-escape backslashed character.
211         *out++ = yych;
212         continue;
213       }
214     }
215
216     }
217
218     int len = (int)(out - filename);
219     const bool is_target = parsing_targets;
220     if (len > 0 && filename[len - 1] == ':') {
221       len--;  // Strip off trailing colon, if any.
222       parsing_targets = false;
223     }
224
225     if (len == 0)
226       continue;
227
228     if (!is_target) {
229       ins_.push_back(StringPiece(filename, len));
230     } else if (!out_.str_) {
231       out_ = StringPiece(filename, len);
232     } else if (out_ != StringPiece(filename, len)) {
233       *err = "depfile has multiple output paths";
234       return false;
235     }
236   }
237   if (parsing_targets) {
238     *err = "expected ':' in depfile";
239     return false;
240   }
241   return true;
242 }