Ninja
|
00001 /* Generated by re2c 0.13.5 */ 00002 // Copyright 2011 Google Inc. All Rights Reserved. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 00016 #include "depfile_parser.h" 00017 00018 // A note on backslashes in Makefiles, from reading the docs: 00019 // Backslash-newline is the line continuation character. 00020 // Backslash-# escapes a # (otherwise meaningful as a comment start). 00021 // Backslash-% escapes a % (otherwise meaningful as a special). 00022 // Finally, quoting the GNU manual, "Backslashes that are not in danger 00023 // of quoting ‘%’ characters go unmolested." 00024 // How do you end a line with a backslash? The netbsd Make docs suggest 00025 // reading the result of a shell command echoing a backslash! 00026 // 00027 // Rather than implement all of above, we do a simpler thing here: 00028 // Backslashes escape a set of characters (see "escapes" defined below), 00029 // otherwise they are passed through verbatim. 00030 // If anyone actually has depfiles that rely on the more complicated 00031 // behavior we can adjust this. 00032 bool DepfileParser::Parse(string* content, string* err) { 00033 // in: current parser input point. 00034 // end: end of input. 00035 // parsing_targets: whether we are parsing targets or dependencies. 00036 char* in = &(*content)[0]; 00037 char* end = in + content->size(); 00038 bool parsing_targets = true; 00039 while (in < end) { 00040 // out: current output point (typically same as in, but can fall behind 00041 // as we de-escape backslashes). 00042 char* out = in; 00043 // filename: start of the current parsed filename. 00044 char* filename = out; 00045 for (;;) { 00046 // start: beginning of the current parsed span. 00047 const char* start = in; 00048 00049 { 00050 char yych; 00051 static const unsigned char yybm[] = { 00052 0, 0, 0, 0, 0, 0, 0, 0, 00053 0, 0, 0, 0, 0, 0, 0, 0, 00054 0, 0, 0, 0, 0, 0, 0, 0, 00055 0, 0, 0, 0, 0, 0, 0, 0, 00056 0, 128, 128, 128, 128, 128, 128, 128, 00057 128, 128, 128, 128, 128, 128, 128, 128, 00058 128, 128, 128, 128, 128, 128, 128, 128, 00059 128, 128, 128, 128, 128, 128, 0, 0, 00060 128, 128, 128, 128, 128, 128, 128, 128, 00061 128, 128, 128, 128, 128, 128, 128, 128, 00062 128, 128, 128, 128, 128, 128, 128, 128, 00063 128, 128, 128, 0, 0, 0, 0, 128, 00064 0, 128, 128, 128, 128, 128, 128, 128, 00065 128, 128, 128, 128, 128, 128, 128, 128, 00066 128, 128, 128, 128, 128, 128, 128, 128, 00067 128, 128, 128, 0, 0, 0, 128, 0, 00068 0, 0, 0, 0, 0, 0, 0, 0, 00069 0, 0, 0, 0, 0, 0, 0, 0, 00070 0, 0, 0, 0, 0, 0, 0, 0, 00071 0, 0, 0, 0, 0, 0, 0, 0, 00072 0, 0, 0, 0, 0, 0, 0, 0, 00073 0, 0, 0, 0, 0, 0, 0, 0, 00074 0, 0, 0, 0, 0, 0, 0, 0, 00075 0, 0, 0, 0, 0, 0, 0, 0, 00076 0, 0, 0, 0, 0, 0, 0, 0, 00077 0, 0, 0, 0, 0, 0, 0, 0, 00078 0, 0, 0, 0, 0, 0, 0, 0, 00079 0, 0, 0, 0, 0, 0, 0, 0, 00080 0, 0, 0, 0, 0, 0, 0, 0, 00081 0, 0, 0, 0, 0, 0, 0, 0, 00082 0, 0, 0, 0, 0, 0, 0, 0, 00083 0, 0, 0, 0, 0, 0, 0, 0, 00084 }; 00085 00086 yych = *in; 00087 if (yych <= '[') { 00088 if (yych <= '$') { 00089 if (yych <= 0x00) goto yy7; 00090 if (yych <= ' ') goto yy9; 00091 if (yych <= '#') goto yy6; 00092 goto yy4; 00093 } else { 00094 if (yych <= '=') goto yy6; 00095 if (yych <= '?') goto yy9; 00096 if (yych <= 'Z') goto yy6; 00097 goto yy9; 00098 } 00099 } else { 00100 if (yych <= '`') { 00101 if (yych <= '\\') goto yy2; 00102 if (yych == '_') goto yy6; 00103 goto yy9; 00104 } else { 00105 if (yych <= 'z') goto yy6; 00106 if (yych == '~') goto yy6; 00107 goto yy9; 00108 } 00109 } 00110 yy2: 00111 ++in; 00112 if ((yych = *in) <= '#') { 00113 if (yych <= '\n') { 00114 if (yych <= 0x00) goto yy3; 00115 if (yych <= '\t') goto yy14; 00116 } else { 00117 if (yych == ' ') goto yy16; 00118 if (yych <= '"') goto yy14; 00119 goto yy16; 00120 } 00121 } else { 00122 if (yych <= 'Z') { 00123 if (yych == '*') goto yy16; 00124 goto yy14; 00125 } else { 00126 if (yych <= '\\') goto yy16; 00127 if (yych == '|') goto yy16; 00128 goto yy14; 00129 } 00130 } 00131 yy3: 00132 { 00133 // For any other character (e.g. whitespace), swallow it here, 00134 // allowing the outer logic to loop around again. 00135 break; 00136 } 00137 yy4: 00138 ++in; 00139 if ((yych = *in) == '$') goto yy12; 00140 goto yy11; 00141 yy5: 00142 { 00143 // Got a span of plain text. 00144 int len = (int)(in - start); 00145 // Need to shift it over if we're overwriting backslashes. 00146 if (out < start) 00147 memmove(out, start, len); 00148 out += len; 00149 continue; 00150 } 00151 yy6: 00152 yych = *++in; 00153 goto yy11; 00154 yy7: 00155 ++in; 00156 { 00157 break; 00158 } 00159 yy9: 00160 yych = *++in; 00161 goto yy3; 00162 yy10: 00163 ++in; 00164 yych = *in; 00165 yy11: 00166 if (yybm[0+yych] & 128) { 00167 goto yy10; 00168 } 00169 goto yy5; 00170 yy12: 00171 ++in; 00172 if (yybm[0+(yych = *in)] & 128) { 00173 goto yy10; 00174 } 00175 { 00176 // De-escape dollar character. 00177 *out++ = '$'; 00178 continue; 00179 } 00180 yy14: 00181 ++in; 00182 { 00183 // Let backslash before other characters through verbatim. 00184 *out++ = '\\'; 00185 *out++ = yych; 00186 continue; 00187 } 00188 yy16: 00189 ++in; 00190 { 00191 // De-escape backslashed character. 00192 *out++ = yych; 00193 continue; 00194 } 00195 } 00196 00197 } 00198 00199 int len = (int)(out - filename); 00200 const bool is_target = parsing_targets; 00201 if (len > 0 && filename[len - 1] == ':') { 00202 len--; // Strip off trailing colon, if any. 00203 parsing_targets = false; 00204 } 00205 00206 if (len == 0) 00207 continue; 00208 00209 if (!is_target) { 00210 ins_.push_back(StringPiece(filename, len)); 00211 } else if (!out_.str_) { 00212 out_ = StringPiece(filename, len); 00213 } else if (out_ != StringPiece(filename, len)) { 00214 *err = "depfile has multiple output paths."; 00215 return false; 00216 } 00217 } 00218 return true; 00219 }