| OLD | NEW |
| 1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 // | 29 // |
| 30 // Author: Satoru Takabayashi | 30 // Author: Satoru Takabayashi |
| 31 // |
| 32 // For reference check out: |
| 33 // http://www.codesourcery.com/public/cxx-abi/abi.html#mangling |
| 34 // |
| 35 // Note that we only have partial C++0x support yet. |
| 31 | 36 |
| 32 #include <stdio.h> // for NULL | 37 #include <stdio.h> // for NULL |
| 33 #include "demangle.h" | 38 #include "demangle.h" |
| 34 | 39 |
| 35 _START_GOOGLE_NAMESPACE_ | 40 _START_GOOGLE_NAMESPACE_ |
| 36 | 41 |
| 37 typedef struct { | 42 typedef struct { |
| 38 const char *abbrev; | 43 const char *abbrev; |
| 39 const char *real_name; | 44 const char *real_name; |
| 40 } AbbrevPair; | 45 } AbbrevPair; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 // std::basic_ostream<char, std::char_traits<char> > | 136 // std::basic_ostream<char, std::char_traits<char> > |
| 132 { "So", "ostream" }, | 137 { "So", "ostream" }, |
| 133 // std::basic_iostream<char, std::char_traits<char> > | 138 // std::basic_iostream<char, std::char_traits<char> > |
| 134 { "Sd", "iostream" }, | 139 { "Sd", "iostream" }, |
| 135 { NULL, NULL } | 140 { NULL, NULL } |
| 136 }; | 141 }; |
| 137 | 142 |
| 138 // State needed for demangling. | 143 // State needed for demangling. |
| 139 typedef struct { | 144 typedef struct { |
| 140 const char *mangled_cur; // Cursor of mangled name. | 145 const char *mangled_cur; // Cursor of mangled name. |
| 141 const char *mangled_end; // End of mangled name. | |
| 142 char *out_cur; // Cursor of output string. | 146 char *out_cur; // Cursor of output string. |
| 143 const char *out_begin; // Beginning of output string. | 147 const char *out_begin; // Beginning of output string. |
| 144 const char *out_end; // End of output string. | 148 const char *out_end; // End of output string. |
| 145 const char *prev_name; // For constructors/destructors. | 149 const char *prev_name; // For constructors/destructors. |
| 146 int prev_name_length; // For constructors/destructors. | 150 int prev_name_length; // For constructors/destructors. |
| 147 int nest_level; // For nested names. | 151 short nest_level; // For nested names. |
| 148 int number; // Remember the previous number. | |
| 149 bool append; // Append flag. | 152 bool append; // Append flag. |
| 150 bool overflowed; // True if output gets overflowed. | 153 bool overflowed; // True if output gets overflowed. |
| 151 } State; | 154 } State; |
| 152 | 155 |
| 153 // We don't use strlen() in libc since it's not guaranteed to be async | 156 // We don't use strlen() in libc since it's not guaranteed to be async |
| 154 // signal safe. | 157 // signal safe. |
| 155 static size_t StrLen(const char *str) { | 158 static size_t StrLen(const char *str) { |
| 156 size_t len = 0; | 159 size_t len = 0; |
| 157 while (*str != '\0') { | 160 while (*str != '\0') { |
| 158 ++str; | 161 ++str; |
| 159 ++len; | 162 ++len; |
| 160 } | 163 } |
| 161 return len; | 164 return len; |
| 162 } | 165 } |
| 163 | 166 |
| 167 // Returns true if "str" has at least "n" characters remaining. |
| 168 static bool AtLeastNumCharsRemaining(const char *str, int n) { |
| 169 for (int i = 0; i < n; ++i) { |
| 170 if (str[i] == '\0') { |
| 171 return false; |
| 172 } |
| 173 } |
| 174 return true; |
| 175 } |
| 176 |
| 164 // Returns true if "str" has "prefix" as a prefix. | 177 // Returns true if "str" has "prefix" as a prefix. |
| 165 static bool StrPrefix(const char *str, const char *prefix) { | 178 static bool StrPrefix(const char *str, const char *prefix) { |
| 166 size_t i = 0; | 179 size_t i = 0; |
| 167 while (str[i] != '\0' && prefix[i] != '\0' && | 180 while (str[i] != '\0' && prefix[i] != '\0' && |
| 168 str[i] == prefix[i]) { | 181 str[i] == prefix[i]) { |
| 169 ++i; | 182 ++i; |
| 170 } | 183 } |
| 171 return prefix[i] == '\0'; // Consumed everything in "prefix". | 184 return prefix[i] == '\0'; // Consumed everything in "prefix". |
| 172 } | 185 } |
| 173 | 186 |
| 174 static void InitState(State *state, const char *mangled, | 187 static void InitState(State *state, const char *mangled, |
| 175 char *out, int out_size) { | 188 char *out, int out_size) { |
| 176 state->mangled_cur = mangled; | 189 state->mangled_cur = mangled; |
| 177 state->mangled_end = mangled + StrLen(mangled); | |
| 178 state->out_cur = out; | 190 state->out_cur = out; |
| 179 state->out_begin = out; | 191 state->out_begin = out; |
| 180 state->out_end = out + out_size; | 192 state->out_end = out + out_size; |
| 181 state->prev_name = NULL; | 193 state->prev_name = NULL; |
| 182 state->prev_name_length = -1; | 194 state->prev_name_length = -1; |
| 183 state->nest_level = -1; | 195 state->nest_level = -1; |
| 184 state->number = -1; | |
| 185 state->append = true; | 196 state->append = true; |
| 186 state->overflowed = false; | 197 state->overflowed = false; |
| 187 } | 198 } |
| 188 | 199 |
| 189 // Calculates the remaining length of the mangled name. | 200 // Returns true and advances "mangled_cur" if we find "one_char_token" |
| 190 static int RemainingLength(State *state) { | 201 // at "mangled_cur" position. It is assumed that "one_char_token" does |
| 191 return state->mangled_end - state->mangled_cur; | 202 // not contain '\0'. |
| 192 } | 203 static bool ParseOneCharToken(State *state, const char one_char_token) { |
| 193 | 204 if (state->mangled_cur[0] == one_char_token) { |
| 194 // Returns true and advances "mangled_cur" if we find "c" at | |
| 195 // "mangled_cur" position. | |
| 196 static bool ParseChar(State *state, const char c) { | |
| 197 if (RemainingLength(state) >= 1 && *state->mangled_cur == c) { | |
| 198 ++state->mangled_cur; | 205 ++state->mangled_cur; |
| 199 return true; | 206 return true; |
| 200 } | 207 } |
| 201 return false; | 208 return false; |
| 202 } | 209 } |
| 203 | 210 |
| 204 // Returns true and advances "mangled_cur" if we find "two_chars" at | 211 // Returns true and advances "mangled_cur" if we find "two_char_token" |
| 205 // "mangled_cur" position. | 212 // at "mangled_cur" position. It is assumed that "two_char_token" does |
| 206 static bool ParseTwoChar(State *state, const char *two_chars) { | 213 // not contain '\0'. |
| 207 if (RemainingLength(state) >= 2 && | 214 static bool ParseTwoCharToken(State *state, const char *two_char_token) { |
| 208 state->mangled_cur[0] == two_chars[0] && | 215 if (state->mangled_cur[0] == two_char_token[0] && |
| 209 state->mangled_cur[1] == two_chars[1]) { | 216 state->mangled_cur[1] == two_char_token[1]) { |
| 210 state->mangled_cur += 2; | 217 state->mangled_cur += 2; |
| 211 return true; | 218 return true; |
| 212 } | 219 } |
| 213 return false; | 220 return false; |
| 214 } | 221 } |
| 215 | 222 |
| 216 // Returns true and advances "mangled_cur" if we find any character in | 223 // Returns true and advances "mangled_cur" if we find any character in |
| 217 // "char_class" at "mangled_cur" position. | 224 // "char_class" at "mangled_cur" position. |
| 218 static bool ParseCharClass(State *state, const char *char_class) { | 225 static bool ParseCharClass(State *state, const char *char_class) { |
| 219 if (state->mangled_cur == state->mangled_end) { | |
| 220 return false; | |
| 221 } | |
| 222 const char *p = char_class; | 226 const char *p = char_class; |
| 223 for (; *p != '\0'; ++p) { | 227 for (; *p != '\0'; ++p) { |
| 224 if (*state->mangled_cur == *p) { | 228 if (state->mangled_cur[0] == *p) { |
| 225 state->mangled_cur += 1; | 229 ++state->mangled_cur; |
| 226 return true; | 230 return true; |
| 227 } | 231 } |
| 228 } | 232 } |
| 229 return false; | 233 return false; |
| 230 } | 234 } |
| 231 | 235 |
| 232 // This function is used for handling an optional non-terminal. | 236 // This function is used for handling an optional non-terminal. |
| 233 static bool Optional(bool status) { | 237 static bool Optional(bool) { |
| 234 return true; | 238 return true; |
| 235 } | 239 } |
| 236 | 240 |
| 237 // This function is used for handling <non-terminal>+ syntax. | 241 // This function is used for handling <non-terminal>+ syntax. |
| 238 typedef bool (*ParseFunc)(State *); | 242 typedef bool (*ParseFunc)(State *); |
| 239 static bool OneOrMore(ParseFunc parse_func, State *state) { | 243 static bool OneOrMore(ParseFunc parse_func, State *state) { |
| 240 if (parse_func(state)) { | 244 if (parse_func(state)) { |
| 241 while (parse_func(state)) { | 245 while (parse_func(state)) { |
| 242 } | 246 } |
| 243 return true; | 247 return true; |
| 244 } | 248 } |
| 245 return false; | 249 return false; |
| 246 } | 250 } |
| 247 | 251 |
| 252 // This function is used for handling <non-terminal>* syntax. The function |
| 253 // always returns true and must be followed by a termination token or a |
| 254 // terminating sequence not handled by parse_func (e.g. |
| 255 // ParseOneCharToken(state, 'E')). |
| 256 static bool ZeroOrMore(ParseFunc parse_func, State *state) { |
| 257 while (parse_func(state)) { |
| 258 } |
| 259 return true; |
| 260 } |
| 261 |
| 248 // Append "str" at "out_cur". If there is an overflow, "overflowed" | 262 // Append "str" at "out_cur". If there is an overflow, "overflowed" |
| 249 // is set to true for later use. The output string is ensured to | 263 // is set to true for later use. The output string is ensured to |
| 250 // always terminate with '\0' as long as there is no overflow. | 264 // always terminate with '\0' as long as there is no overflow. |
| 251 static void Append(State *state, const char * const str, const int length) { | 265 static void Append(State *state, const char * const str, const int length) { |
| 252 int i; | 266 int i; |
| 253 for (i = 0; i < length; ++i) { | 267 for (i = 0; i < length; ++i) { |
| 254 if (state->out_cur + 1 < state->out_end) { // +1 for '\0' | 268 if (state->out_cur + 1 < state->out_end) { // +1 for '\0' |
| 255 *state->out_cur = str[i]; | 269 *state->out_cur = str[i]; |
| 256 ++state->out_cur; | 270 ++state->out_cur; |
| 257 } else { | 271 } else { |
| 258 state->overflowed = true; | 272 state->overflowed = true; |
| 259 break; | 273 break; |
| 260 } | 274 } |
| 261 } | 275 } |
| 262 if (!state->overflowed) { | 276 if (!state->overflowed) { |
| 263 *state->out_cur = '\0'; // Terminate it with '\0' | 277 *state->out_cur = '\0'; // Terminate it with '\0' |
| 264 } | 278 } |
| 265 } | 279 } |
| 266 | 280 |
| 267 // We don't use equivalents in libc to avoid locale issues. | 281 // We don't use equivalents in libc to avoid locale issues. |
| 268 static bool IsLower(char c) { | 282 static bool IsLower(char c) { |
| 269 return c >= 'a' && c <= 'z'; | 283 return c >= 'a' && c <= 'z'; |
| 270 } | 284 } |
| 271 | 285 |
| 272 static bool IsAlpha(char c) { | 286 static bool IsAlpha(char c) { |
| 273 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); | 287 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); |
| 288 } |
| 289 |
| 290 static bool IsDigit(char c) { |
| 291 return c >= '0' && c <= '9'; |
| 292 } |
| 293 |
| 294 // Returns true if "str" is a function clone suffix. These suffixes are used |
| 295 // by GCC 4.5.x and later versions to indicate functions which have been |
| 296 // cloned during optimization. We treat any sequence (.<alpha>+.<digit>+)+ as |
| 297 // a function clone suffix. |
| 298 static bool IsFunctionCloneSuffix(const char *str) { |
| 299 size_t i = 0; |
| 300 while (str[i] != '\0') { |
| 301 // Consume a single .<alpha>+.<digit>+ sequence. |
| 302 if (str[i] != '.' || !IsAlpha(str[i + 1])) { |
| 303 return false; |
| 304 } |
| 305 i += 2; |
| 306 while (IsAlpha(str[i])) { |
| 307 ++i; |
| 308 } |
| 309 if (str[i] != '.' || !IsDigit(str[i + 1])) { |
| 310 return false; |
| 311 } |
| 312 i += 2; |
| 313 while (IsDigit(str[i])) { |
| 314 ++i; |
| 315 } |
| 316 } |
| 317 return true; // Consumed everything in "str". |
| 274 } | 318 } |
| 275 | 319 |
| 276 // Append "str" with some tweaks, iff "append" state is true. | 320 // Append "str" with some tweaks, iff "append" state is true. |
| 277 // Returns true so that it can be placed in "if" conditions. | 321 // Returns true so that it can be placed in "if" conditions. |
| 278 static void MaybeAppendWithLength(State *state, const char * const str, | 322 static void MaybeAppendWithLength(State *state, const char * const str, |
| 279 const int length) { | 323 const int length) { |
| 280 if (state->append && length > 0) { | 324 if (state->append && length > 0) { |
| 281 // Append a space if the output buffer ends with '<' and "str" | 325 // Append a space if the output buffer ends with '<' and "str" |
| 282 // starts with '<' to avoid <<<. | 326 // starts with '<' to avoid <<<. |
| 283 if (str[0] == '<' && state->out_begin < state->out_cur && | 327 if (str[0] == '<' && state->out_begin < state->out_cur && |
| (...skipping 18 matching lines...) Expand all Loading... |
| 302 return true; | 346 return true; |
| 303 } | 347 } |
| 304 | 348 |
| 305 // This function is used for handling nested names. | 349 // This function is used for handling nested names. |
| 306 static bool EnterNestedName(State *state) { | 350 static bool EnterNestedName(State *state) { |
| 307 state->nest_level = 0; | 351 state->nest_level = 0; |
| 308 return true; | 352 return true; |
| 309 } | 353 } |
| 310 | 354 |
| 311 // This function is used for handling nested names. | 355 // This function is used for handling nested names. |
| 312 static bool LeaveNestedName(State *state, int prev_value) { | 356 static bool LeaveNestedName(State *state, short prev_value) { |
| 313 state->nest_level = prev_value; | 357 state->nest_level = prev_value; |
| 314 return true; | 358 return true; |
| 315 } | 359 } |
| 316 | 360 |
| 317 // Disable the append mode not to print function parameters, etc. | 361 // Disable the append mode not to print function parameters, etc. |
| 318 static bool DisableAppend(State *state) { | 362 static bool DisableAppend(State *state) { |
| 319 state->append = false; | 363 state->append = false; |
| 320 return true; | 364 return true; |
| 321 } | 365 } |
| 322 | 366 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 342 | 386 |
| 343 // Cancel the last separator if necessary. | 387 // Cancel the last separator if necessary. |
| 344 static void MaybeCancelLastSeparator(State *state) { | 388 static void MaybeCancelLastSeparator(State *state) { |
| 345 if (state->nest_level >= 1 && state->append && | 389 if (state->nest_level >= 1 && state->append && |
| 346 state->out_begin <= state->out_cur - 2) { | 390 state->out_begin <= state->out_cur - 2) { |
| 347 state->out_cur -= 2; | 391 state->out_cur -= 2; |
| 348 *state->out_cur = '\0'; | 392 *state->out_cur = '\0'; |
| 349 } | 393 } |
| 350 } | 394 } |
| 351 | 395 |
| 352 // Returns true if identifier pointed by "mangled_cur" is anonymous | 396 // Returns true if the identifier of the given length pointed to by |
| 353 // namespace. | 397 // "mangled_cur" is anonymous namespace. |
| 354 static bool IdentifierIsAnonymousNamespace(State *state) { | 398 static bool IdentifierIsAnonymousNamespace(State *state, int length) { |
| 355 const char anon_prefix[] = "_GLOBAL__N_"; | 399 static const char anon_prefix[] = "_GLOBAL__N_"; |
| 356 return (state->number > sizeof(anon_prefix) - 1 && // Should be longer. | 400 return (length > (int)sizeof(anon_prefix) - 1 && // Should be longer. |
| 357 StrPrefix(state->mangled_cur, anon_prefix)); | 401 StrPrefix(state->mangled_cur, anon_prefix)); |
| 358 } | 402 } |
| 359 | 403 |
| 360 // Forward declarations of our parsing functions. | 404 // Forward declarations of our parsing functions. |
| 361 static bool ParseMangledName(State *state); | 405 static bool ParseMangledName(State *state); |
| 362 static bool ParseEncoding(State *state); | 406 static bool ParseEncoding(State *state); |
| 363 static bool ParseName(State *state); | 407 static bool ParseName(State *state); |
| 364 static bool ParseUnscopedName(State *state); | 408 static bool ParseUnscopedName(State *state); |
| 365 static bool ParseUnscopedTemplateName(State *state); | 409 static bool ParseUnscopedTemplateName(State *state); |
| 366 static bool ParseNestedName(State *state); | 410 static bool ParseNestedName(State *state); |
| 367 static bool ParsePrefix(State *state); | 411 static bool ParsePrefix(State *state); |
| 368 static bool ParseUnqualifiedName(State *state); | 412 static bool ParseUnqualifiedName(State *state); |
| 369 static bool ParseSourceName(State *state); | 413 static bool ParseSourceName(State *state); |
| 370 static bool ParseLocalSourceName(State *state); | 414 static bool ParseLocalSourceName(State *state); |
| 371 static bool ParseNumber(State *state); | 415 static bool ParseNumber(State *state, int *number_out); |
| 372 static bool ParseFloatNumber(State *state); | 416 static bool ParseFloatNumber(State *state); |
| 373 static bool ParseSeqId(State *state); | 417 static bool ParseSeqId(State *state); |
| 374 static bool ParseIdentifier(State *state); | 418 static bool ParseIdentifier(State *state, int length); |
| 375 static bool ParseOperatorName(State *state); | 419 static bool ParseOperatorName(State *state); |
| 376 static bool ParseSpecialName(State *state); | 420 static bool ParseSpecialName(State *state); |
| 377 static bool ParseCallOffset(State *state); | 421 static bool ParseCallOffset(State *state); |
| 378 static bool ParseNVOffset(State *state); | 422 static bool ParseNVOffset(State *state); |
| 379 static bool ParseVOffset(State *state); | 423 static bool ParseVOffset(State *state); |
| 380 static bool ParseCtorDtorName(State *state); | 424 static bool ParseCtorDtorName(State *state); |
| 381 static bool ParseType(State *state); | 425 static bool ParseType(State *state); |
| 382 static bool ParseCVQualifiers(State *state); | 426 static bool ParseCVQualifiers(State *state); |
| 383 static bool ParseBuiltinType(State *state); | 427 static bool ParseBuiltinType(State *state); |
| 384 static bool ParseFunctionType(State *state); | 428 static bool ParseFunctionType(State *state); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 // cp-demangle.c has +4300 lines). | 465 // cp-demangle.c has +4300 lines). |
| 422 // | 466 // |
| 423 // Note that (foo) in <(foo) ...> is a modifier to be ignored. | 467 // Note that (foo) in <(foo) ...> is a modifier to be ignored. |
| 424 // | 468 // |
| 425 // Reference: | 469 // Reference: |
| 426 // - Itanium C++ ABI | 470 // - Itanium C++ ABI |
| 427 // <http://www.codesourcery.com/cxx-abi/abi.html#mangling> | 471 // <http://www.codesourcery.com/cxx-abi/abi.html#mangling> |
| 428 | 472 |
| 429 // <mangled-name> ::= _Z <encoding> | 473 // <mangled-name> ::= _Z <encoding> |
| 430 static bool ParseMangledName(State *state) { | 474 static bool ParseMangledName(State *state) { |
| 431 if (ParseTwoChar(state, "_Z") && ParseEncoding(state)) { | 475 return ParseTwoCharToken(state, "_Z") && ParseEncoding(state); |
| 432 // Append trailing version suffix if any. | |
| 433 // ex. _Z3foo@@GLIBCXX_3.4 | |
| 434 if (state->mangled_cur < state->mangled_end && | |
| 435 state->mangled_cur[0] == '@') { | |
| 436 MaybeAppend(state, state->mangled_cur); | |
| 437 state->mangled_cur = state->mangled_end; | |
| 438 } | |
| 439 return true; | |
| 440 } | |
| 441 return false; | |
| 442 } | 476 } |
| 443 | 477 |
| 444 // <encoding> ::= <(function) name> <bare-function-type> | 478 // <encoding> ::= <(function) name> <bare-function-type> |
| 445 // ::= <(data) name> | 479 // ::= <(data) name> |
| 446 // ::= <special-name> | 480 // ::= <special-name> |
| 447 static bool ParseEncoding(State *state) { | 481 static bool ParseEncoding(State *state) { |
| 448 State copy = *state; | 482 State copy = *state; |
| 449 if (ParseName(state) && ParseBareFunctionType(state)) { | 483 if (ParseName(state) && ParseBareFunctionType(state)) { |
| 450 return true; | 484 return true; |
| 451 } | 485 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 481 } | 515 } |
| 482 | 516 |
| 483 // <unscoped-name> ::= <unqualified-name> | 517 // <unscoped-name> ::= <unqualified-name> |
| 484 // ::= St <unqualified-name> | 518 // ::= St <unqualified-name> |
| 485 static bool ParseUnscopedName(State *state) { | 519 static bool ParseUnscopedName(State *state) { |
| 486 if (ParseUnqualifiedName(state)) { | 520 if (ParseUnqualifiedName(state)) { |
| 487 return true; | 521 return true; |
| 488 } | 522 } |
| 489 | 523 |
| 490 State copy = *state; | 524 State copy = *state; |
| 491 if (ParseTwoChar(state, "St") && | 525 if (ParseTwoCharToken(state, "St") && |
| 492 MaybeAppend(state, "std::") && | 526 MaybeAppend(state, "std::") && |
| 493 ParseUnqualifiedName(state)) { | 527 ParseUnqualifiedName(state)) { |
| 494 return true; | 528 return true; |
| 495 } | 529 } |
| 496 *state = copy; | 530 *state = copy; |
| 497 return false; | 531 return false; |
| 498 } | 532 } |
| 499 | 533 |
| 500 // <unscoped-template-name> ::= <unscoped-name> | 534 // <unscoped-template-name> ::= <unscoped-name> |
| 501 // ::= <substitution> | 535 // ::= <substitution> |
| 502 static bool ParseUnscopedTemplateName(State *state) { | 536 static bool ParseUnscopedTemplateName(State *state) { |
| 503 return ParseUnscopedName(state) || ParseSubstitution(state); | 537 return ParseUnscopedName(state) || ParseSubstitution(state); |
| 504 } | 538 } |
| 505 | 539 |
| 506 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E | 540 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E |
| 507 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E | 541 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E |
| 508 static bool ParseNestedName(State *state) { | 542 static bool ParseNestedName(State *state) { |
| 509 State copy = *state; | 543 State copy = *state; |
| 510 if (ParseChar(state, 'N') && | 544 if (ParseOneCharToken(state, 'N') && |
| 511 EnterNestedName(state) && | 545 EnterNestedName(state) && |
| 512 Optional(ParseCVQualifiers(state)) && | 546 Optional(ParseCVQualifiers(state)) && |
| 513 ParsePrefix(state) && | 547 ParsePrefix(state) && |
| 514 LeaveNestedName(state, copy.nest_level) && | 548 LeaveNestedName(state, copy.nest_level) && |
| 515 ParseChar(state, 'E')) { | 549 ParseOneCharToken(state, 'E')) { |
| 516 return true; | 550 return true; |
| 517 } | 551 } |
| 518 *state = copy; | 552 *state = copy; |
| 519 return false; | 553 return false; |
| 520 } | 554 } |
| 521 | 555 |
| 522 // This part is tricky. If we literally translate them to code, we'll | 556 // This part is tricky. If we literally translate them to code, we'll |
| 523 // end up infinite loop. Hence we merge them to avoid the case. | 557 // end up infinite loop. Hence we merge them to avoid the case. |
| 524 // | 558 // |
| 525 // <prefix> ::= <prefix> <unqualified-name> | 559 // <prefix> ::= <prefix> <unqualified-name> |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 static bool ParseUnqualifiedName(State *state) { | 592 static bool ParseUnqualifiedName(State *state) { |
| 559 return (ParseOperatorName(state) || | 593 return (ParseOperatorName(state) || |
| 560 ParseCtorDtorName(state) || | 594 ParseCtorDtorName(state) || |
| 561 ParseSourceName(state) || | 595 ParseSourceName(state) || |
| 562 ParseLocalSourceName(state)); | 596 ParseLocalSourceName(state)); |
| 563 } | 597 } |
| 564 | 598 |
| 565 // <source-name> ::= <positive length number> <identifier> | 599 // <source-name> ::= <positive length number> <identifier> |
| 566 static bool ParseSourceName(State *state) { | 600 static bool ParseSourceName(State *state) { |
| 567 State copy = *state; | 601 State copy = *state; |
| 568 if (ParseNumber(state) && ParseIdentifier(state)) { | 602 int length = -1; |
| 603 if (ParseNumber(state, &length) && ParseIdentifier(state, length)) { |
| 569 return true; | 604 return true; |
| 570 } | 605 } |
| 571 *state = copy; | 606 *state = copy; |
| 572 return false; | 607 return false; |
| 573 } | 608 } |
| 574 | 609 |
| 575 // <local-source-name> ::= L <source-name> [<discriminator>] | 610 // <local-source-name> ::= L <source-name> [<discriminator>] |
| 576 // | 611 // |
| 577 // References: | 612 // References: |
| 578 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775 | 613 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775 |
| 579 // http://gcc.gnu.org/viewcvs?view=rev&revision=124467 | 614 // http://gcc.gnu.org/viewcvs?view=rev&revision=124467 |
| 580 static bool ParseLocalSourceName(State *state) { | 615 static bool ParseLocalSourceName(State *state) { |
| 581 State copy = *state; | 616 State copy = *state; |
| 582 if (ParseChar(state, 'L') && ParseSourceName(state) && | 617 if (ParseOneCharToken(state, 'L') && ParseSourceName(state) && |
| 583 Optional(ParseDiscriminator(state))) { | 618 Optional(ParseDiscriminator(state))) { |
| 584 return true; | 619 return true; |
| 585 } | 620 } |
| 586 *state = copy; | 621 *state = copy; |
| 587 return false; | 622 return false; |
| 588 } | 623 } |
| 589 | 624 |
| 590 // <number> ::= [n] <non-negative decimal integer> | 625 // <number> ::= [n] <non-negative decimal integer> |
| 591 static bool ParseNumber(State *state) { | 626 // If "number_out" is non-null, then *number_out is set to the value of the |
| 627 // parsed number on success. |
| 628 static bool ParseNumber(State *state, int *number_out) { |
| 592 int sign = 1; | 629 int sign = 1; |
| 593 if (ParseChar(state, 'n')) { | 630 if (ParseOneCharToken(state, 'n')) { |
| 594 sign = -1; | 631 sign = -1; |
| 595 } | 632 } |
| 596 const char *p = state->mangled_cur; | 633 const char *p = state->mangled_cur; |
| 597 int number = 0; | 634 int number = 0; |
| 598 for (;p < state->mangled_end; ++p) { | 635 for (;*p != '\0'; ++p) { |
| 599 if ((*p >= '0' && *p <= '9')) { | 636 if (IsDigit(*p)) { |
| 600 number = number * 10 + (*p - '0'); | 637 number = number * 10 + (*p - '0'); |
| 601 } else { | 638 } else { |
| 602 break; | 639 break; |
| 603 } | 640 } |
| 604 } | 641 } |
| 605 if (p != state->mangled_cur) { // Conversion succeeded. | 642 if (p != state->mangled_cur) { // Conversion succeeded. |
| 606 state->mangled_cur = p; | 643 state->mangled_cur = p; |
| 607 state->number = number * sign; | 644 if (number_out != NULL) { |
| 645 *number_out = number * sign; |
| 646 } |
| 608 return true; | 647 return true; |
| 609 } | 648 } |
| 610 return false; | 649 return false; |
| 611 } | 650 } |
| 612 | 651 |
| 613 // Floating-point literals are encoded using a fixed-length lowercase | 652 // Floating-point literals are encoded using a fixed-length lowercase |
| 614 // hexadecimal string. | 653 // hexadecimal string. |
| 615 static bool ParseFloatNumber(State *state) { | 654 static bool ParseFloatNumber(State *state) { |
| 616 const char *p = state->mangled_cur; | 655 const char *p = state->mangled_cur; |
| 617 int number = 0; | 656 for (;*p != '\0'; ++p) { |
| 618 for (;p < state->mangled_end; ++p) { | 657 if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) { |
| 619 if ((*p >= '0' && *p <= '9')) { | |
| 620 number = number * 16 + (*p - '0'); | |
| 621 } else if (*p >= 'a' && *p <= 'f') { | |
| 622 number = number * 16 + (*p - 'a' + 10); | |
| 623 } else { | |
| 624 break; | 658 break; |
| 625 } | 659 } |
| 626 } | 660 } |
| 627 if (p != state->mangled_cur) { // Conversion succeeded. | 661 if (p != state->mangled_cur) { // Conversion succeeded. |
| 628 state->mangled_cur = p; | 662 state->mangled_cur = p; |
| 629 state->number = number; | |
| 630 return true; | 663 return true; |
| 631 } | 664 } |
| 632 return false; | 665 return false; |
| 633 } | 666 } |
| 634 | 667 |
| 635 // The <seq-id> is a sequence number in base 36, | 668 // The <seq-id> is a sequence number in base 36, |
| 636 // using digits and upper case letters | 669 // using digits and upper case letters |
| 637 static bool ParseSeqId(State *state) { | 670 static bool ParseSeqId(State *state) { |
| 638 const char *p = state->mangled_cur; | 671 const char *p = state->mangled_cur; |
| 639 int number = 0; | 672 for (;*p != '\0'; ++p) { |
| 640 for (;p < state->mangled_end; ++p) { | 673 if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) { |
| 641 if ((*p >= '0' && *p <= '9')) { | |
| 642 number = number * 36 + (*p - '0'); | |
| 643 } else if (*p >= 'A' && *p <= 'Z') { | |
| 644 number = number * 36 + (*p - 'A' + 10); | |
| 645 } else { | |
| 646 break; | 674 break; |
| 647 } | 675 } |
| 648 } | 676 } |
| 649 if (p != state->mangled_cur) { // Conversion succeeded. | 677 if (p != state->mangled_cur) { // Conversion succeeded. |
| 650 state->mangled_cur = p; | 678 state->mangled_cur = p; |
| 651 state->number = number; | |
| 652 return true; | 679 return true; |
| 653 } | 680 } |
| 654 return false; | 681 return false; |
| 655 } | 682 } |
| 656 | 683 |
| 657 // <identifier> ::= <unqualified source code identifier> | 684 // <identifier> ::= <unqualified source code identifier> (of given length) |
| 658 static bool ParseIdentifier(State *state) { | 685 static bool ParseIdentifier(State *state, int length) { |
| 659 if (state->number == -1 || | 686 if (length == -1 || |
| 660 RemainingLength(state) < state->number) { | 687 !AtLeastNumCharsRemaining(state->mangled_cur, length)) { |
| 661 return false; | 688 return false; |
| 662 } | 689 } |
| 663 if (IdentifierIsAnonymousNamespace(state)) { | 690 if (IdentifierIsAnonymousNamespace(state, length)) { |
| 664 MaybeAppend(state, "(anonymous namespace)"); | 691 MaybeAppend(state, "(anonymous namespace)"); |
| 665 } else { | 692 } else { |
| 666 MaybeAppendWithLength(state, state->mangled_cur, state->number); | 693 MaybeAppendWithLength(state, state->mangled_cur, length); |
| 667 } | 694 } |
| 668 state->mangled_cur += state->number; | 695 state->mangled_cur += length; |
| 669 state->number = -1; // Reset the number. | |
| 670 return true; | 696 return true; |
| 671 } | 697 } |
| 672 | 698 |
| 673 // <operator-name> ::= nw, and other two letters cases | 699 // <operator-name> ::= nw, and other two letters cases |
| 674 // ::= cv <type> # (cast) | 700 // ::= cv <type> # (cast) |
| 675 // ::= v <digit> <source-name> # vendor extended operator | 701 // ::= v <digit> <source-name> # vendor extended operator |
| 676 static bool ParseOperatorName(State *state) { | 702 static bool ParseOperatorName(State *state) { |
| 677 if (RemainingLength(state) < 2) { | 703 if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) { |
| 678 return false; | 704 return false; |
| 679 } | 705 } |
| 680 // First check with "cv" (cast) case. | 706 // First check with "cv" (cast) case. |
| 681 State copy = *state; | 707 State copy = *state; |
| 682 if (ParseTwoChar(state, "cv") && | 708 if (ParseTwoCharToken(state, "cv") && |
| 683 MaybeAppend(state, "operator ") && | 709 MaybeAppend(state, "operator ") && |
| 684 EnterNestedName(state) && | 710 EnterNestedName(state) && |
| 685 ParseType(state) && | 711 ParseType(state) && |
| 686 LeaveNestedName(state, copy.nest_level)) { | 712 LeaveNestedName(state, copy.nest_level)) { |
| 687 return true; | 713 return true; |
| 688 } | 714 } |
| 689 *state = copy; | 715 *state = copy; |
| 690 | 716 |
| 691 // Then vendor extended operators. | 717 // Then vendor extended operators. |
| 692 if (ParseChar(state, 'v') && ParseCharClass(state, "0123456789") && | 718 if (ParseOneCharToken(state, 'v') && ParseCharClass(state, "0123456789") && |
| 693 ParseSourceName(state)) { | 719 ParseSourceName(state)) { |
| 694 return true; | 720 return true; |
| 695 } | 721 } |
| 696 *state = copy; | 722 *state = copy; |
| 697 | 723 |
| 698 // Other operator names should start with a lower alphabet followed | 724 // Other operator names should start with a lower alphabet followed |
| 699 // by a lower/upper alphabet. | 725 // by a lower/upper alphabet. |
| 700 if (!(IsLower(state->mangled_cur[0]) && | 726 if (!(IsLower(state->mangled_cur[0]) && |
| 701 IsAlpha(state->mangled_cur[1]))) { | 727 IsAlpha(state->mangled_cur[1]))) { |
| 702 return false; | 728 return false; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 731 // ::= TJ <type> | 757 // ::= TJ <type> |
| 732 // ::= GR <name> | 758 // ::= GR <name> |
| 733 // ::= GA <encoding> | 759 // ::= GA <encoding> |
| 734 // ::= Th <call-offset> <(base) encoding> | 760 // ::= Th <call-offset> <(base) encoding> |
| 735 // ::= Tv <call-offset> <(base) encoding> | 761 // ::= Tv <call-offset> <(base) encoding> |
| 736 // | 762 // |
| 737 // Note: we don't care much about them since they don't appear in | 763 // Note: we don't care much about them since they don't appear in |
| 738 // stack traces. The are special data. | 764 // stack traces. The are special data. |
| 739 static bool ParseSpecialName(State *state) { | 765 static bool ParseSpecialName(State *state) { |
| 740 State copy = *state; | 766 State copy = *state; |
| 741 if (ParseChar(state, 'T') && | 767 if (ParseOneCharToken(state, 'T') && |
| 742 ParseCharClass(state, "VTIS") && | 768 ParseCharClass(state, "VTIS") && |
| 743 ParseType(state)) { | 769 ParseType(state)) { |
| 744 return true; | 770 return true; |
| 745 } | 771 } |
| 746 *state = copy; | 772 *state = copy; |
| 747 | 773 |
| 748 if (ParseTwoChar(state, "Tc") && ParseCallOffset(state) && | 774 if (ParseTwoCharToken(state, "Tc") && ParseCallOffset(state) && |
| 749 ParseCallOffset(state) && ParseEncoding(state)) { | 775 ParseCallOffset(state) && ParseEncoding(state)) { |
| 750 return true; | 776 return true; |
| 751 } | 777 } |
| 752 *state = copy; | 778 *state = copy; |
| 753 | 779 |
| 754 if (ParseTwoChar(state, "GV") && | 780 if (ParseTwoCharToken(state, "GV") && |
| 755 ParseName(state)) { | 781 ParseName(state)) { |
| 756 return true; | 782 return true; |
| 757 } | 783 } |
| 758 *state = copy; | 784 *state = copy; |
| 759 | 785 |
| 760 if (ParseChar(state, 'T') && ParseCallOffset(state) && | 786 if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) && |
| 761 ParseEncoding(state)) { | 787 ParseEncoding(state)) { |
| 762 return true; | 788 return true; |
| 763 } | 789 } |
| 764 *state = copy; | 790 *state = copy; |
| 765 | 791 |
| 766 // G++ extensions | 792 // G++ extensions |
| 767 if (ParseTwoChar(state, "TC") && ParseType(state) && | 793 if (ParseTwoCharToken(state, "TC") && ParseType(state) && |
| 768 ParseNumber(state) && ParseChar(state, '_') && | 794 ParseNumber(state, NULL) && ParseOneCharToken(state, '_') && |
| 769 DisableAppend(state) && | 795 DisableAppend(state) && |
| 770 ParseType(state)) { | 796 ParseType(state)) { |
| 771 RestoreAppend(state, copy.append); | 797 RestoreAppend(state, copy.append); |
| 772 return true; | 798 return true; |
| 773 } | 799 } |
| 774 *state = copy; | 800 *state = copy; |
| 775 | 801 |
| 776 if (ParseChar(state, 'T') && ParseCharClass(state, "FJ") && | 802 if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "FJ") && |
| 777 ParseType(state)) { | 803 ParseType(state)) { |
| 778 return true; | 804 return true; |
| 779 } | 805 } |
| 780 *state = copy; | 806 *state = copy; |
| 781 | 807 |
| 782 if (ParseTwoChar(state, "GR") && ParseName(state)) { | 808 if (ParseTwoCharToken(state, "GR") && ParseName(state)) { |
| 783 return true; | 809 return true; |
| 784 } | 810 } |
| 785 *state = copy; | 811 *state = copy; |
| 786 | 812 |
| 787 if (ParseTwoChar(state, "GA") && ParseEncoding(state)) { | 813 if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) { |
| 788 return true; | 814 return true; |
| 789 } | 815 } |
| 790 *state = copy; | 816 *state = copy; |
| 791 | 817 |
| 792 if (ParseChar(state, 'T') && ParseCharClass(state, "hv") && | 818 if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "hv") && |
| 793 ParseCallOffset(state) && ParseEncoding(state)) { | 819 ParseCallOffset(state) && ParseEncoding(state)) { |
| 794 return true; | 820 return true; |
| 795 } | 821 } |
| 796 *state = copy; | 822 *state = copy; |
| 797 return false; | 823 return false; |
| 798 } | 824 } |
| 799 | 825 |
| 800 // <call-offset> ::= h <nv-offset> _ | 826 // <call-offset> ::= h <nv-offset> _ |
| 801 // ::= v <v-offset> _ | 827 // ::= v <v-offset> _ |
| 802 static bool ParseCallOffset(State *state) { | 828 static bool ParseCallOffset(State *state) { |
| 803 State copy = *state; | 829 State copy = *state; |
| 804 if (ParseChar(state, 'h') && | 830 if (ParseOneCharToken(state, 'h') && |
| 805 ParseNVOffset(state) && ParseChar(state, '_')) { | 831 ParseNVOffset(state) && ParseOneCharToken(state, '_')) { |
| 806 return true; | 832 return true; |
| 807 } | 833 } |
| 808 *state = copy; | 834 *state = copy; |
| 809 | 835 |
| 810 if (ParseChar(state, 'v') && | 836 if (ParseOneCharToken(state, 'v') && |
| 811 ParseVOffset(state) && ParseChar(state, '_')) { | 837 ParseVOffset(state) && ParseOneCharToken(state, '_')) { |
| 812 return true; | 838 return true; |
| 813 } | 839 } |
| 814 *state = copy; | 840 *state = copy; |
| 815 | 841 |
| 816 return false; | 842 return false; |
| 817 } | 843 } |
| 818 | 844 |
| 819 // <nv-offset> ::= <(offset) number> | 845 // <nv-offset> ::= <(offset) number> |
| 820 static bool ParseNVOffset(State *state) { | 846 static bool ParseNVOffset(State *state) { |
| 821 return ParseNumber(state); | 847 return ParseNumber(state, NULL); |
| 822 } | 848 } |
| 823 | 849 |
| 824 // <v-offset> ::= <(offset) number> _ <(virtual offset) number> | 850 // <v-offset> ::= <(offset) number> _ <(virtual offset) number> |
| 825 static bool ParseVOffset(State *state) { | 851 static bool ParseVOffset(State *state) { |
| 826 State copy = *state; | 852 State copy = *state; |
| 827 if (ParseNumber(state) && ParseChar(state, '_') && | 853 if (ParseNumber(state, NULL) && ParseOneCharToken(state, '_') && |
| 828 ParseNumber(state)) { | 854 ParseNumber(state, NULL)) { |
| 829 return true; | 855 return true; |
| 830 } | 856 } |
| 831 *state = copy; | 857 *state = copy; |
| 832 return false; | 858 return false; |
| 833 } | 859 } |
| 834 | 860 |
| 835 // <ctor-dtor-name> ::= C1 | C2 | C3 | 861 // <ctor-dtor-name> ::= C1 | C2 | C3 |
| 836 // ::= D0 | D1 | D2 | 862 // ::= D0 | D1 | D2 |
| 837 static bool ParseCtorDtorName(State *state) { | 863 static bool ParseCtorDtorName(State *state) { |
| 838 State copy = *state; | 864 State copy = *state; |
| 839 if (ParseChar(state, 'C') && | 865 if (ParseOneCharToken(state, 'C') && |
| 840 ParseCharClass(state, "123")) { | 866 ParseCharClass(state, "123")) { |
| 841 const char * const prev_name = state->prev_name; | 867 const char * const prev_name = state->prev_name; |
| 842 const int prev_name_length = state->prev_name_length; | 868 const int prev_name_length = state->prev_name_length; |
| 843 MaybeAppendWithLength(state, prev_name, prev_name_length); | 869 MaybeAppendWithLength(state, prev_name, prev_name_length); |
| 844 return true; | 870 return true; |
| 845 } | 871 } |
| 846 *state = copy; | 872 *state = copy; |
| 847 | 873 |
| 848 if (ParseChar(state, 'D') && | 874 if (ParseOneCharToken(state, 'D') && |
| 849 ParseCharClass(state, "012")) { | 875 ParseCharClass(state, "012")) { |
| 850 const char * const prev_name = state->prev_name; | 876 const char * const prev_name = state->prev_name; |
| 851 const int prev_name_length = state->prev_name_length; | 877 const int prev_name_length = state->prev_name_length; |
| 852 MaybeAppend(state, "~"); | 878 MaybeAppend(state, "~"); |
| 853 MaybeAppendWithLength(state, prev_name, prev_name_length); | 879 MaybeAppendWithLength(state, prev_name, prev_name_length); |
| 854 return true; | 880 return true; |
| 855 } | 881 } |
| 856 *state = copy; | 882 *state = copy; |
| 857 return false; | 883 return false; |
| 858 } | 884 } |
| 859 | 885 |
| 860 // <type> ::= <CV-qualifiers> <type> | 886 // <type> ::= <CV-qualifiers> <type> |
| 861 // ::= P <type> | 887 // ::= P <type> # pointer-to |
| 862 // ::= R <type> | 888 // ::= R <type> # reference-to |
| 863 // ::= C <type> | 889 // ::= O <type> # rvalue reference-to (C++0x) |
| 864 // ::= G <type> | 890 // ::= C <type> # complex pair (C 2000) |
| 865 // ::= U <source-name> <type> | 891 // ::= G <type> # imaginary (C 2000) |
| 892 // ::= U <source-name> <type> # vendor extended type qualifier |
| 866 // ::= <builtin-type> | 893 // ::= <builtin-type> |
| 867 // ::= <function-type> | 894 // ::= <function-type> |
| 868 // ::= <class-enum-type> | 895 // ::= <class-enum-type> |
| 869 // ::= <array-type> | 896 // ::= <array-type> |
| 870 // ::= <pointer-to-member-type> | 897 // ::= <pointer-to-member-type> |
| 871 // ::= <template-template-param> <template-args> | 898 // ::= <template-template-param> <template-args> |
| 872 // ::= <template-param> | 899 // ::= <template-param> |
| 873 // ::= <substitution> | 900 // ::= <substitution> |
| 901 // ::= Dp <type> # pack expansion of (C++0x) |
| 902 // ::= Dt <expression> E # decltype of an id-expression or class |
| 903 // # member access (C++0x) |
| 904 // ::= DT <expression> E # decltype of an expression (C++0x) |
| 905 // |
| 874 static bool ParseType(State *state) { | 906 static bool ParseType(State *state) { |
| 875 // We should check CV-qualifers, and PRGC things first. | 907 // We should check CV-qualifers, and PRGC things first. |
| 876 State copy = *state; | 908 State copy = *state; |
| 877 if (ParseCVQualifiers(state) && ParseType(state)) { | 909 if (ParseCVQualifiers(state) && ParseType(state)) { |
| 878 return true; | 910 return true; |
| 879 } | 911 } |
| 880 *state = copy; | 912 *state = copy; |
| 881 | 913 |
| 882 if (ParseCharClass(state, "PRCG") && ParseType(state)) { | 914 if (ParseCharClass(state, "OPRCG") && ParseType(state)) { |
| 883 return true; | 915 return true; |
| 884 } | 916 } |
| 885 *state = copy; | 917 *state = copy; |
| 886 | 918 |
| 887 if (ParseChar(state, 'U') && ParseSourceName(state) && | 919 if (ParseTwoCharToken(state, "Dp") && ParseType(state)) { |
| 920 return true; |
| 921 } |
| 922 *state = copy; |
| 923 |
| 924 if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") && |
| 925 ParseExpression(state) && ParseOneCharToken(state, 'E')) { |
| 926 return true; |
| 927 } |
| 928 *state = copy; |
| 929 |
| 930 if (ParseOneCharToken(state, 'U') && ParseSourceName(state) && |
| 888 ParseType(state)) { | 931 ParseType(state)) { |
| 889 return true; | 932 return true; |
| 890 } | 933 } |
| 891 *state = copy; | 934 *state = copy; |
| 892 | 935 |
| 893 if (ParseBuiltinType(state) || | 936 if (ParseBuiltinType(state) || |
| 894 ParseFunctionType(state) || | 937 ParseFunctionType(state) || |
| 895 ParseClassEnumType(state) || | 938 ParseClassEnumType(state) || |
| 896 ParseArrayType(state) || | 939 ParseArrayType(state) || |
| 897 ParsePointerToMemberType(state) || | 940 ParsePointerToMemberType(state) || |
| (...skipping 13 matching lines...) Expand all Loading... |
| 911 } | 954 } |
| 912 | 955 |
| 913 return false; | 956 return false; |
| 914 } | 957 } |
| 915 | 958 |
| 916 // <CV-qualifiers> ::= [r] [V] [K] | 959 // <CV-qualifiers> ::= [r] [V] [K] |
| 917 // We don't allow empty <CV-qualifiers> to avoid infinite loop in | 960 // We don't allow empty <CV-qualifiers> to avoid infinite loop in |
| 918 // ParseType(). | 961 // ParseType(). |
| 919 static bool ParseCVQualifiers(State *state) { | 962 static bool ParseCVQualifiers(State *state) { |
| 920 int num_cv_qualifiers = 0; | 963 int num_cv_qualifiers = 0; |
| 921 num_cv_qualifiers += ParseChar(state, 'r'); | 964 num_cv_qualifiers += ParseOneCharToken(state, 'r'); |
| 922 num_cv_qualifiers += ParseChar(state, 'V'); | 965 num_cv_qualifiers += ParseOneCharToken(state, 'V'); |
| 923 num_cv_qualifiers += ParseChar(state, 'K'); | 966 num_cv_qualifiers += ParseOneCharToken(state, 'K'); |
| 924 return num_cv_qualifiers > 0; | 967 return num_cv_qualifiers > 0; |
| 925 } | 968 } |
| 926 | 969 |
| 927 // <builtin-type> ::= v, etc. | 970 // <builtin-type> ::= v, etc. |
| 928 // ::= u <source-name> | 971 // ::= u <source-name> |
| 929 static bool ParseBuiltinType(State *state) { | 972 static bool ParseBuiltinType(State *state) { |
| 930 const AbbrevPair *p; | 973 const AbbrevPair *p; |
| 931 for (p = kBuiltinTypeList; p->abbrev != NULL; ++p) { | 974 for (p = kBuiltinTypeList; p->abbrev != NULL; ++p) { |
| 932 if (state->mangled_cur[0] == p->abbrev[0]) { | 975 if (state->mangled_cur[0] == p->abbrev[0]) { |
| 933 MaybeAppend(state, p->real_name); | 976 MaybeAppend(state, p->real_name); |
| 934 ++state->mangled_cur; | 977 ++state->mangled_cur; |
| 935 return true; | 978 return true; |
| 936 } | 979 } |
| 937 } | 980 } |
| 938 | 981 |
| 939 State copy = *state; | 982 State copy = *state; |
| 940 if (ParseChar(state, 'u') && ParseSourceName(state)) { | 983 if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) { |
| 941 return true; | 984 return true; |
| 942 } | 985 } |
| 943 *state = copy; | 986 *state = copy; |
| 944 return false; | 987 return false; |
| 945 } | 988 } |
| 946 | 989 |
| 947 // <function-type> ::= F [Y] <bare-function-type> E | 990 // <function-type> ::= F [Y] <bare-function-type> E |
| 948 static bool ParseFunctionType(State *state) { | 991 static bool ParseFunctionType(State *state) { |
| 949 State copy = *state; | 992 State copy = *state; |
| 950 if (ParseChar(state, 'F') && Optional(ParseChar(state, 'Y')) && | 993 if (ParseOneCharToken(state, 'F') && |
| 951 ParseBareFunctionType(state) && ParseChar(state, 'E')) { | 994 Optional(ParseOneCharToken(state, 'Y')) && |
| 995 ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) { |
| 952 return true; | 996 return true; |
| 953 } | 997 } |
| 954 *state = copy; | 998 *state = copy; |
| 955 return false; | 999 return false; |
| 956 } | 1000 } |
| 957 | 1001 |
| 958 // <bare-function-type> ::= <(signature) type>+ | 1002 // <bare-function-type> ::= <(signature) type>+ |
| 959 static bool ParseBareFunctionType(State *state) { | 1003 static bool ParseBareFunctionType(State *state) { |
| 960 State copy = *state; | 1004 State copy = *state; |
| 961 DisableAppend(state); | 1005 DisableAppend(state); |
| 962 if (OneOrMore(ParseType, state)) { | 1006 if (OneOrMore(ParseType, state)) { |
| 963 RestoreAppend(state, copy.append); | 1007 RestoreAppend(state, copy.append); |
| 964 MaybeAppend(state, "()"); | 1008 MaybeAppend(state, "()"); |
| 965 return true; | 1009 return true; |
| 966 } | 1010 } |
| 967 *state = copy; | 1011 *state = copy; |
| 968 return false; | 1012 return false; |
| 969 } | 1013 } |
| 970 | 1014 |
| 971 // <class-enum-type> ::= <name> | 1015 // <class-enum-type> ::= <name> |
| 972 static bool ParseClassEnumType(State *state) { | 1016 static bool ParseClassEnumType(State *state) { |
| 973 return ParseName(state); | 1017 return ParseName(state); |
| 974 } | 1018 } |
| 975 | 1019 |
| 976 // <array-type> ::= A <(positive dimension) number> _ <(element) type> | 1020 // <array-type> ::= A <(positive dimension) number> _ <(element) type> |
| 977 // ::= A [<(dimension) expression>] _ <(element) type> | 1021 // ::= A [<(dimension) expression>] _ <(element) type> |
| 978 static bool ParseArrayType(State *state) { | 1022 static bool ParseArrayType(State *state) { |
| 979 State copy = *state; | 1023 State copy = *state; |
| 980 if (ParseChar(state, 'A') && ParseNumber(state) && | 1024 if (ParseOneCharToken(state, 'A') && ParseNumber(state, NULL) && |
| 981 ParseChar(state, '_') && ParseType(state)) { | 1025 ParseOneCharToken(state, '_') && ParseType(state)) { |
| 982 return true; | 1026 return true; |
| 983 } | 1027 } |
| 984 *state = copy; | 1028 *state = copy; |
| 985 | 1029 |
| 986 if (ParseChar(state, 'A') && Optional(ParseExpression(state)) && | 1030 if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) && |
| 987 ParseChar(state, '_') && ParseType(state)) { | 1031 ParseOneCharToken(state, '_') && ParseType(state)) { |
| 988 return true; | 1032 return true; |
| 989 } | 1033 } |
| 990 *state = copy; | 1034 *state = copy; |
| 991 return false; | 1035 return false; |
| 992 } | 1036 } |
| 993 | 1037 |
| 994 // <pointer-to-member-type> ::= M <(class) type> <(member) type> | 1038 // <pointer-to-member-type> ::= M <(class) type> <(member) type> |
| 995 static bool ParsePointerToMemberType(State *state) { | 1039 static bool ParsePointerToMemberType(State *state) { |
| 996 State copy = *state; | 1040 State copy = *state; |
| 997 if (ParseChar(state, 'M') && ParseType(state) && | 1041 if (ParseOneCharToken(state, 'M') && ParseType(state) && |
| 998 ParseType(state)) { | 1042 ParseType(state)) { |
| 999 return true; | 1043 return true; |
| 1000 } | 1044 } |
| 1001 *state = copy; | 1045 *state = copy; |
| 1002 return false; | 1046 return false; |
| 1003 } | 1047 } |
| 1004 | 1048 |
| 1005 // <template-param> ::= T_ | 1049 // <template-param> ::= T_ |
| 1006 // ::= T <parameter-2 non-negative number> _ | 1050 // ::= T <parameter-2 non-negative number> _ |
| 1007 static bool ParseTemplateParam(State *state) { | 1051 static bool ParseTemplateParam(State *state) { |
| 1008 if (ParseTwoChar(state, "T_")) { | 1052 if (ParseTwoCharToken(state, "T_")) { |
| 1009 MaybeAppend(state, "?"); // We don't support template substitutions. | 1053 MaybeAppend(state, "?"); // We don't support template substitutions. |
| 1010 return true; | 1054 return true; |
| 1011 } | 1055 } |
| 1012 | 1056 |
| 1013 State copy = *state; | 1057 State copy = *state; |
| 1014 if (ParseChar(state, 'T') && ParseNumber(state) && | 1058 if (ParseOneCharToken(state, 'T') && ParseNumber(state, NULL) && |
| 1015 ParseChar(state, '_')) { | 1059 ParseOneCharToken(state, '_')) { |
| 1016 MaybeAppend(state, "?"); // We don't support template substitutions. | 1060 MaybeAppend(state, "?"); // We don't support template substitutions. |
| 1017 return true; | 1061 return true; |
| 1018 } | 1062 } |
| 1019 *state = copy; | 1063 *state = copy; |
| 1020 return false; | 1064 return false; |
| 1021 } | 1065 } |
| 1022 | 1066 |
| 1023 | 1067 |
| 1024 // <template-template-param> ::= <template-param> | 1068 // <template-template-param> ::= <template-param> |
| 1025 // ::= <substitution> | 1069 // ::= <substitution> |
| 1026 static bool ParseTemplateTemplateParam(State *state) { | 1070 static bool ParseTemplateTemplateParam(State *state) { |
| 1027 return (ParseTemplateParam(state) || | 1071 return (ParseTemplateParam(state) || |
| 1028 ParseSubstitution(state)); | 1072 ParseSubstitution(state)); |
| 1029 } | 1073 } |
| 1030 | 1074 |
| 1031 // <template-args> ::= I <template-arg>+ E | 1075 // <template-args> ::= I <template-arg>+ E |
| 1032 static bool ParseTemplateArgs(State *state) { | 1076 static bool ParseTemplateArgs(State *state) { |
| 1033 State copy = *state; | 1077 State copy = *state; |
| 1034 DisableAppend(state); | 1078 DisableAppend(state); |
| 1035 if (ParseChar(state, 'I') && | 1079 if (ParseOneCharToken(state, 'I') && |
| 1036 OneOrMore(ParseTemplateArg, state) && | 1080 OneOrMore(ParseTemplateArg, state) && |
| 1037 ParseChar(state, 'E')) { | 1081 ParseOneCharToken(state, 'E')) { |
| 1038 RestoreAppend(state, copy.append); | 1082 RestoreAppend(state, copy.append); |
| 1039 MaybeAppend(state, "<>"); | 1083 MaybeAppend(state, "<>"); |
| 1040 return true; | 1084 return true; |
| 1041 } | 1085 } |
| 1042 *state = copy; | 1086 *state = copy; |
| 1043 return false; | 1087 return false; |
| 1044 } | 1088 } |
| 1045 | 1089 |
| 1046 // <template-arg> ::= <type> | 1090 // <template-arg> ::= <type> |
| 1047 // ::= <expr-primary> | 1091 // ::= <expr-primary> |
| 1092 // ::= I <template-arg>* E # argument pack |
| 1048 // ::= X <expression> E | 1093 // ::= X <expression> E |
| 1049 static bool ParseTemplateArg(State *state) { | 1094 static bool ParseTemplateArg(State *state) { |
| 1095 State copy = *state; |
| 1096 if (ParseOneCharToken(state, 'I') && |
| 1097 ZeroOrMore(ParseTemplateArg, state) && |
| 1098 ParseOneCharToken(state, 'E')) { |
| 1099 return true; |
| 1100 } |
| 1101 *state = copy; |
| 1102 |
| 1050 if (ParseType(state) || | 1103 if (ParseType(state) || |
| 1051 ParseExprPrimary(state)) { | 1104 ParseExprPrimary(state)) { |
| 1052 return true; | 1105 return true; |
| 1053 } | 1106 } |
| 1107 *state = copy; |
| 1054 | 1108 |
| 1055 State copy = *state; | 1109 if (ParseOneCharToken(state, 'X') && ParseExpression(state) && |
| 1056 if (ParseChar(state, 'X') && ParseExpression(state) && | 1110 ParseOneCharToken(state, 'E')) { |
| 1057 ParseChar(state, 'E')) { | |
| 1058 return true; | 1111 return true; |
| 1059 } | 1112 } |
| 1060 *state = copy; | 1113 *state = copy; |
| 1061 return false; | 1114 return false; |
| 1062 } | 1115 } |
| 1063 | 1116 |
| 1064 // <expression> ::= <template-param> | 1117 // <expression> ::= <template-param> |
| 1065 // ::= <expr-primary> | 1118 // ::= <expr-primary> |
| 1066 // ::= <unary operator-name> <expression> | 1119 // ::= <unary operator-name> <expression> |
| 1067 // ::= <binary operator-name> <expression> <expression> | 1120 // ::= <binary operator-name> <expression> <expression> |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1090 return true; | 1143 return true; |
| 1091 } | 1144 } |
| 1092 *state = copy; | 1145 *state = copy; |
| 1093 | 1146 |
| 1094 if (ParseOperatorName(state) && | 1147 if (ParseOperatorName(state) && |
| 1095 ParseExpression(state)) { | 1148 ParseExpression(state)) { |
| 1096 return true; | 1149 return true; |
| 1097 } | 1150 } |
| 1098 *state = copy; | 1151 *state = copy; |
| 1099 | 1152 |
| 1100 if (ParseTwoChar(state, "st") && ParseType(state)) { | 1153 if (ParseTwoCharToken(state, "st") && ParseType(state)) { |
| 1101 return true; | 1154 return true; |
| 1102 } | 1155 } |
| 1103 *state = copy; | 1156 *state = copy; |
| 1104 | 1157 |
| 1105 if (ParseTwoChar(state, "sr") && ParseType(state) && | 1158 if (ParseTwoCharToken(state, "sr") && ParseType(state) && |
| 1106 ParseUnqualifiedName(state) && | 1159 ParseUnqualifiedName(state) && |
| 1107 ParseTemplateArgs(state)) { | 1160 ParseTemplateArgs(state)) { |
| 1108 return true; | 1161 return true; |
| 1109 } | 1162 } |
| 1110 *state = copy; | 1163 *state = copy; |
| 1111 | 1164 |
| 1112 if (ParseTwoChar(state, "sr") && ParseType(state) && | 1165 if (ParseTwoCharToken(state, "sr") && ParseType(state) && |
| 1113 ParseUnqualifiedName(state)) { | 1166 ParseUnqualifiedName(state)) { |
| 1114 return true; | 1167 return true; |
| 1115 } | 1168 } |
| 1116 *state = copy; | 1169 *state = copy; |
| 1117 return false; | 1170 return false; |
| 1118 } | 1171 } |
| 1119 | 1172 |
| 1120 // <expr-primary> ::= L <type> <(value) number> E | 1173 // <expr-primary> ::= L <type> <(value) number> E |
| 1121 // ::= L <type> <(value) float> E | 1174 // ::= L <type> <(value) float> E |
| 1122 // ::= L <mangled-name> E | 1175 // ::= L <mangled-name> E |
| 1123 // // A bug in g++'s C++ ABI version 2 (-fabi-version=2). | 1176 // // A bug in g++'s C++ ABI version 2 (-fabi-version=2). |
| 1124 // ::= LZ <encoding> E | 1177 // ::= LZ <encoding> E |
| 1125 static bool ParseExprPrimary(State *state) { | 1178 static bool ParseExprPrimary(State *state) { |
| 1126 State copy = *state; | 1179 State copy = *state; |
| 1127 if (ParseChar(state, 'L') && ParseType(state) && | 1180 if (ParseOneCharToken(state, 'L') && ParseType(state) && |
| 1128 ParseNumber(state) && | 1181 ParseNumber(state, NULL) && |
| 1129 ParseChar(state, 'E')) { | 1182 ParseOneCharToken(state, 'E')) { |
| 1130 return true; | 1183 return true; |
| 1131 } | 1184 } |
| 1132 *state = copy; | 1185 *state = copy; |
| 1133 | 1186 |
| 1134 if (ParseChar(state, 'L') && ParseType(state) && | 1187 if (ParseOneCharToken(state, 'L') && ParseType(state) && |
| 1135 ParseFloatNumber(state) && | 1188 ParseFloatNumber(state) && |
| 1136 ParseChar(state, 'E')) { | 1189 ParseOneCharToken(state, 'E')) { |
| 1137 return true; | 1190 return true; |
| 1138 } | 1191 } |
| 1139 *state = copy; | 1192 *state = copy; |
| 1140 | 1193 |
| 1141 if (ParseChar(state, 'L') && ParseMangledName(state) && | 1194 if (ParseOneCharToken(state, 'L') && ParseMangledName(state) && |
| 1142 ParseChar(state, 'E')) { | 1195 ParseOneCharToken(state, 'E')) { |
| 1143 return true; | 1196 return true; |
| 1144 } | 1197 } |
| 1145 *state = copy; | 1198 *state = copy; |
| 1146 | 1199 |
| 1147 if (ParseTwoChar(state, "LZ") && ParseEncoding(state) && | 1200 if (ParseTwoCharToken(state, "LZ") && ParseEncoding(state) && |
| 1148 ParseChar(state, 'E')) { | 1201 ParseOneCharToken(state, 'E')) { |
| 1149 return true; | 1202 return true; |
| 1150 } | 1203 } |
| 1151 *state = copy; | 1204 *state = copy; |
| 1152 | 1205 |
| 1153 return false; | 1206 return false; |
| 1154 } | 1207 } |
| 1155 | 1208 |
| 1156 // <local-name> := Z <(function) encoding> E <(entity) name> | 1209 // <local-name> := Z <(function) encoding> E <(entity) name> |
| 1157 // [<discriminator>] | 1210 // [<discriminator>] |
| 1158 // := Z <(function) encoding> E s [<discriminator>] | 1211 // := Z <(function) encoding> E s [<discriminator>] |
| 1159 static bool ParseLocalName(State *state) { | 1212 static bool ParseLocalName(State *state) { |
| 1160 State copy = *state; | 1213 State copy = *state; |
| 1161 if (ParseChar(state, 'Z') && ParseEncoding(state) && | 1214 if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) && |
| 1162 ParseChar(state, 'E') && MaybeAppend(state, "::") && | 1215 ParseOneCharToken(state, 'E') && MaybeAppend(state, "::") && |
| 1163 ParseName(state) && Optional(ParseDiscriminator(state))) { | 1216 ParseName(state) && Optional(ParseDiscriminator(state))) { |
| 1164 return true; | 1217 return true; |
| 1165 } | 1218 } |
| 1166 *state = copy; | 1219 *state = copy; |
| 1167 | 1220 |
| 1168 if (ParseChar(state, 'Z') && ParseEncoding(state) && | 1221 if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) && |
| 1169 ParseTwoChar(state, "Es") && Optional(ParseDiscriminator(state))) { | 1222 ParseTwoCharToken(state, "Es") && Optional(ParseDiscriminator(state))) { |
| 1170 return true; | 1223 return true; |
| 1171 } | 1224 } |
| 1172 *state = copy; | 1225 *state = copy; |
| 1173 return false; | 1226 return false; |
| 1174 } | 1227 } |
| 1175 | 1228 |
| 1176 // <discriminator> := _ <(non-negative) number> | 1229 // <discriminator> := _ <(non-negative) number> |
| 1177 static bool ParseDiscriminator(State *state) { | 1230 static bool ParseDiscriminator(State *state) { |
| 1178 State copy = *state; | 1231 State copy = *state; |
| 1179 if (ParseChar(state, '_') && ParseNumber(state)) { | 1232 if (ParseOneCharToken(state, '_') && ParseNumber(state, NULL)) { |
| 1180 return true; | 1233 return true; |
| 1181 } | 1234 } |
| 1182 *state = copy; | 1235 *state = copy; |
| 1183 return false; | 1236 return false; |
| 1184 } | 1237 } |
| 1185 | 1238 |
| 1186 // <substitution> ::= S_ | 1239 // <substitution> ::= S_ |
| 1187 // ::= S <seq-id> _ | 1240 // ::= S <seq-id> _ |
| 1188 // ::= St, etc. | 1241 // ::= St, etc. |
| 1189 static bool ParseSubstitution(State *state) { | 1242 static bool ParseSubstitution(State *state) { |
| 1190 if (ParseTwoChar(state, "S_")) { | 1243 if (ParseTwoCharToken(state, "S_")) { |
| 1191 MaybeAppend(state, "?"); // We don't support substitutions. | 1244 MaybeAppend(state, "?"); // We don't support substitutions. |
| 1192 return true; | 1245 return true; |
| 1193 } | 1246 } |
| 1194 | 1247 |
| 1195 State copy = *state; | 1248 State copy = *state; |
| 1196 if (ParseChar(state, 'S') && ParseSeqId(state) && | 1249 if (ParseOneCharToken(state, 'S') && ParseSeqId(state) && |
| 1197 ParseChar(state, '_')) { | 1250 ParseOneCharToken(state, '_')) { |
| 1198 MaybeAppend(state, "?"); // We don't support substitutions. | 1251 MaybeAppend(state, "?"); // We don't support substitutions. |
| 1199 return true; | 1252 return true; |
| 1200 } | 1253 } |
| 1201 *state = copy; | 1254 *state = copy; |
| 1202 | 1255 |
| 1203 // Expand abbreviations like "St" => "std". | 1256 // Expand abbreviations like "St" => "std". |
| 1204 if (ParseChar(state, 'S')) { | 1257 if (ParseOneCharToken(state, 'S')) { |
| 1205 const AbbrevPair *p; | 1258 const AbbrevPair *p; |
| 1206 for (p = kSubstitutionList; p->abbrev != NULL; ++p) { | 1259 for (p = kSubstitutionList; p->abbrev != NULL; ++p) { |
| 1207 if (state->mangled_cur[0] == p->abbrev[1]) { | 1260 if (state->mangled_cur[0] == p->abbrev[1]) { |
| 1208 MaybeAppend(state, "std"); | 1261 MaybeAppend(state, "std"); |
| 1209 if (p->real_name[0] != '\0') { | 1262 if (p->real_name[0] != '\0') { |
| 1210 MaybeAppend(state, "::"); | 1263 MaybeAppend(state, "::"); |
| 1211 MaybeAppend(state, p->real_name); | 1264 MaybeAppend(state, p->real_name); |
| 1212 } | 1265 } |
| 1213 state->mangled_cur += 1; | 1266 ++state->mangled_cur; |
| 1214 return true; | 1267 return true; |
| 1215 } | 1268 } |
| 1216 } | 1269 } |
| 1217 } | 1270 } |
| 1218 *state = copy; | 1271 *state = copy; |
| 1219 return false; | 1272 return false; |
| 1220 } | 1273 } |
| 1221 | 1274 |
| 1275 // Parse <mangled-name>, optionally followed by either a function-clone suffix |
| 1276 // or version suffix. Returns true only if all of "mangled_cur" was consumed. |
| 1277 static bool ParseTopLevelMangledName(State *state) { |
| 1278 if (ParseMangledName(state)) { |
| 1279 if (state->mangled_cur[0] != '\0') { |
| 1280 // Drop trailing function clone suffix, if any. |
| 1281 if (IsFunctionCloneSuffix(state->mangled_cur)) { |
| 1282 return true; |
| 1283 } |
| 1284 // Append trailing version suffix if any. |
| 1285 // ex. _Z3foo@@GLIBCXX_3.4 |
| 1286 if (state->mangled_cur[0] == '@') { |
| 1287 MaybeAppend(state, state->mangled_cur); |
| 1288 return true; |
| 1289 } |
| 1290 return false; // Unconsumed suffix. |
| 1291 } |
| 1292 return true; |
| 1293 } |
| 1294 return false; |
| 1295 } |
| 1296 |
| 1222 // The demangler entry point. | 1297 // The demangler entry point. |
| 1223 bool Demangle(const char *mangled, char *out, int out_size) { | 1298 bool Demangle(const char *mangled, char *out, int out_size) { |
| 1224 State state; | 1299 State state; |
| 1225 InitState(&state, mangled, out, out_size); | 1300 InitState(&state, mangled, out, out_size); |
| 1226 return (ParseMangledName(&state) && | 1301 return ParseTopLevelMangledName(&state) && !state.overflowed; |
| 1227 state.overflowed == false && | |
| 1228 RemainingLength(&state) == 0); | |
| 1229 } | 1302 } |
| 1230 | 1303 |
| 1231 _END_GOOGLE_NAMESPACE_ | 1304 _END_GOOGLE_NAMESPACE_ |
| OLD | NEW |