Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: base/third_party/symbolize/demangle.cc

Issue 180163013: Copying the following files AS-IS from google.glog r141: (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/third_party/symbolize/README.chromium ('k') | base/third_party/symbolize/symbolize.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « base/third_party/symbolize/README.chromium ('k') | base/third_party/symbolize/symbolize.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698