1 /* Demangler for the Rust programming language
2 Copyright (C) 2016-2022 Free Software Foundation, Inc.
3 Written by David Tolnay (dtolnay@gmail.com).
4 Rewritten by Eduard-Mihai Burtescu (eddyb@lyken.rs) for v0 support.
6 This file is part of the libiberty library.
7 Libiberty is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 In addition to the permissions in the GNU Library General Public
13 License, the Free Software Foundation gives you unlimited permission
14 to link the compiled version of this file into combinations with other
15 programs, and to distribute those combinations without any restriction
16 coming from the use of this file. (The Library Public License
17 restrictions do apply in other respects; for example, they cover
18 modification of the file, and distribution when not linked into a
21 Libiberty is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 Library General Public License for more details.
26 You should have received a copy of the GNU Library General Public
27 License along with libiberty; see the file COPYING.LIB.
28 If not, see <http://www.gnu.org/licenses/>. */
35 #include "safe-ctype.h"
38 #include <sys/types.h>
46 extern size_t strlen(const char *s
);
47 extern int strncmp(const char *s1
, const char *s2
, size_t n
);
48 extern void *memset(void *s
, int c
, size_t n
);
52 #include "libiberty.h"
59 void *callback_opaque
;
60 demangle_callbackref callback
;
62 /* Position of the next character to read from the symbol. */
65 /* Non-zero if any error occurred. */
68 /* Non-zero if nothing should be printed. */
69 int skipping_printing
;
71 /* Non-zero if printing should be verbose (e.g. include hashes). */
74 /* Rust mangling version, with legacy mangling being -1. */
77 /* Recursion depth. */
78 unsigned int recursion
;
79 /* Maximum number of times demangle_path may be called recursively. */
80 #define RUST_MAX_RECURSION_COUNT 1024
81 #define RUST_NO_RECURSION_LIMIT ((unsigned int) -1)
83 uint64_t bound_lifetime_depth
;
86 /* Parsing functions. */
89 peek (const struct rust_demangler
*rdm
)
91 if (rdm
->next
< rdm
->sym_len
)
92 return rdm
->sym
[rdm
->next
];
97 eat (struct rust_demangler
*rdm
, char c
)
109 next (struct rust_demangler
*rdm
)
120 parse_integer_62 (struct rust_demangler
*rdm
)
129 while (!eat (rdm
, '_'))
135 else if (ISLOWER (c
))
137 else if (ISUPPER (c
))
138 x
+= 10 + 26 + (c
- 'A');
149 parse_opt_integer_62 (struct rust_demangler
*rdm
, char tag
)
153 return 1 + parse_integer_62 (rdm
);
157 parse_disambiguator (struct rust_demangler
*rdm
)
159 return parse_opt_integer_62 (rdm
, 's');
163 parse_hex_nibbles (struct rust_demangler
*rdm
, uint64_t *value
)
171 while (!eat (rdm
, '_'))
178 else if (c
>= 'a' && c
<= 'f')
179 *value
|= 10 + (c
- 'a');
191 struct rust_mangled_ident
193 /* ASCII part of the identifier. */
197 /* Punycode insertion codes for Unicode codepoints, if any. */
198 const char *punycode
;
202 static struct rust_mangled_ident
203 parse_ident (struct rust_demangler
*rdm
)
208 struct rust_mangled_ident ident
;
212 ident
.punycode
= NULL
;
213 ident
.punycode_len
= 0;
215 if (rdm
->version
!= -1)
216 is_punycode
= eat (rdm
, 'u');
227 while (ISDIGIT (peek (rdm
)))
228 len
= len
* 10 + (next (rdm
) - '0');
230 /* Skip past the optional `_` separator (v0). */
231 if (rdm
->version
!= -1)
236 /* Check for overflows. */
237 if ((start
> rdm
->next
) || (rdm
->next
> rdm
->sym_len
))
243 ident
.ascii
= rdm
->sym
+ start
;
244 ident
.ascii_len
= len
;
248 ident
.punycode_len
= 0;
249 while (ident
.ascii_len
> 0)
253 /* The last '_' is a separator between ascii & punycode. */
254 if (ident
.ascii
[ident
.ascii_len
] == '_')
257 ident
.punycode_len
++;
259 if (!ident
.punycode_len
)
264 ident
.punycode
= ident
.ascii
+ (len
- ident
.punycode_len
);
267 if (ident
.ascii_len
== 0)
273 /* Printing functions. */
276 print_str (struct rust_demangler
*rdm
, const char *data
, size_t len
)
278 if (!rdm
->errored
&& !rdm
->skipping_printing
)
279 rdm
->callback (data
, len
, rdm
->callback_opaque
);
282 #define PRINT(s) print_str (rdm, s, strlen (s))
285 print_uint64 (struct rust_demangler
*rdm
, uint64_t x
)
288 snprintf (s
, 21, "%" PRIu64
, x
);
293 print_uint64_hex (struct rust_demangler
*rdm
, uint64_t x
)
296 snprintf (s
, 17, "%" PRIx64
, x
);
300 /* Return a 0x0-0xf value if the char is 0-9a-f, and -1 otherwise. */
302 decode_lower_hex_nibble (char nibble
)
304 if ('0' <= nibble
&& nibble
<= '9')
306 if ('a' <= nibble
&& nibble
<= 'f')
307 return 0xa + (nibble
- 'a');
311 /* Return the unescaped character for a "$...$" escape, or 0 if invalid. */
313 decode_legacy_escape (const char *e
, size_t len
, size_t *out_len
)
316 size_t escape_len
= 0;
317 int lo_nibble
= -1, hi_nibble
= -1;
319 if (len
< 3 || e
[0] != '$')
335 if (e
[0] == 'S' && e
[1] == 'P')
337 else if (e
[0] == 'B' && e
[1] == 'P')
339 else if (e
[0] == 'R' && e
[1] == 'F')
341 else if (e
[0] == 'L' && e
[1] == 'T')
343 else if (e
[0] == 'G' && e
[1] == 'T')
345 else if (e
[0] == 'L' && e
[1] == 'P')
347 else if (e
[0] == 'R' && e
[1] == 'P')
349 else if (e
[0] == 'u' && len
> 3)
353 hi_nibble
= decode_lower_hex_nibble (e
[1]);
356 lo_nibble
= decode_lower_hex_nibble (e
[2]);
360 /* Only allow non-control ASCII characters. */
363 c
= (hi_nibble
<< 4) | lo_nibble
;
369 if (!c
|| len
<= escape_len
|| e
[escape_len
] != '$')
372 *out_len
= 2 + escape_len
;
377 print_ident (struct rust_demangler
*rdm
, struct rust_mangled_ident ident
)
381 size_t len
, cap
, punycode_pos
, j
;
382 /* Punycode parameters and state. */
384 size_t base
, t_min
, t_max
, skew
, damp
, bias
, i
;
385 size_t delta
, w
, k
, t
;
387 if (rdm
->errored
|| rdm
->skipping_printing
)
390 if (rdm
->version
== -1)
392 /* Ignore leading underscores preceding escape sequences.
393 The mangler inserts an underscore to make sure the
394 identifier begins with a XID_Start character. */
395 if (ident
.ascii_len
>= 2 && ident
.ascii
[0] == '_'
396 && ident
.ascii
[1] == '$')
402 while (ident
.ascii_len
> 0)
404 /* Handle legacy escape sequences ("$...$", ".." or "."). */
405 if (ident
.ascii
[0] == '$')
408 = decode_legacy_escape (ident
.ascii
, ident
.ascii_len
, &len
);
410 print_str (rdm
, &unescaped
, 1);
413 /* Unexpected escape sequence, print the rest verbatim. */
414 print_str (rdm
, ident
.ascii
, ident
.ascii_len
);
418 else if (ident
.ascii
[0] == '.')
420 if (ident
.ascii_len
>= 2 && ident
.ascii
[1] == '.')
422 /* ".." becomes "::" */
434 /* Print everything before the next escape sequence, at once. */
435 for (len
= 0; len
< ident
.ascii_len
; len
++)
436 if (ident
.ascii
[len
] == '$' || ident
.ascii
[len
] == '.')
439 print_str (rdm
, ident
.ascii
, len
);
443 ident
.ascii_len
-= len
;
451 print_str (rdm
, ident
.ascii
, ident
.ascii_len
);
457 while (cap
< ident
.ascii_len
)
460 /* Check for overflows. */
461 if ((cap
* 4) / 4 != cap
)
468 /* Store the output codepoints as groups of 4 UTF-8 bytes. */
469 out
= (uint8_t *)malloc (cap
* 4);
476 /* Populate initial output from ASCII fragment. */
477 for (len
= 0; len
< ident
.ascii_len
; len
++)
483 p
[3] = ident
.ascii
[len
];
486 /* Punycode parameters and initial state. */
497 while (punycode_pos
< ident
.punycode_len
)
499 /* Read one delta value. */
506 t
= k
< bias
? 0 : (k
- bias
);
512 if (punycode_pos
>= ident
.punycode_len
)
514 d
= ident
.punycode
[punycode_pos
++];
518 else if (ISDIGIT (d
))
531 /* Compute the new insert position and character. */
537 /* Ensure enough space is available. */
541 /* Check for overflows. */
542 if ((cap
* 4) / 4 != cap
|| cap
< len
)
548 p
= (uint8_t *)realloc (out
, cap
* 4);
556 /* Move the characters after the insert position. */
558 memmove (p
+ 4, p
, (len
- i
- 1) * 4);
560 /* Insert the new character, as UTF-8 bytes. */
561 p
[0] = c
>= 0x10000 ? 0xf0 | (c
>> 18) : 0;
562 p
[1] = c
>= 0x800 ? (c
< 0x10000 ? 0xe0 : 0x80) | ((c
>> 12) & 0x3f) : 0;
563 p
[2] = (c
< 0x800 ? 0xc0 : 0x80) | ((c
>> 6) & 0x3f);
564 p
[3] = 0x80 | (c
& 0x3f);
566 /* If there are no more deltas, decoding is complete. */
567 if (punycode_pos
== ident
.punycode_len
)
572 /* Perform bias adaptation. */
576 delta
+= delta
/ len
;
578 while (delta
> ((base
- t_min
) * t_max
) / 2)
580 delta
/= base
- t_min
;
583 bias
= k
+ ((base
- t_min
+ 1) * delta
) / (delta
+ skew
);
586 /* Remove all the 0 bytes to leave behind an UTF-8 string. */
587 for (i
= 0, j
= 0; i
< len
* 4; i
++)
591 print_str (rdm
, (const char *)out
, j
);
597 /* Print the lifetime according to the previously decoded index.
598 An index of `0` always refers to `'_`, but starting with `1`,
599 indices refer to late-bound lifetimes introduced by a binder. */
601 print_lifetime_from_index (struct rust_demangler
*rdm
, uint64_t lt
)
613 depth
= rdm
->bound_lifetime_depth
- lt
;
614 /* Try to print lifetimes alphabetically first. */
618 print_str (rdm
, &c
, 1);
622 /* Use `'_123` after running out of letters. */
624 print_uint64 (rdm
, depth
);
628 /* Demangling functions. */
630 static void demangle_binder (struct rust_demangler
*rdm
);
631 static void demangle_path (struct rust_demangler
*rdm
, int in_value
);
632 static void demangle_generic_arg (struct rust_demangler
*rdm
);
633 static void demangle_type (struct rust_demangler
*rdm
);
634 static int demangle_path_maybe_open_generics (struct rust_demangler
*rdm
);
635 static void demangle_dyn_trait (struct rust_demangler
*rdm
);
636 static void demangle_const (struct rust_demangler
*rdm
);
637 static void demangle_const_uint (struct rust_demangler
*rdm
);
638 static void demangle_const_int (struct rust_demangler
*rdm
);
639 static void demangle_const_bool (struct rust_demangler
*rdm
);
640 static void demangle_const_char (struct rust_demangler
*rdm
);
642 /* Optionally enter a binder ('G') for late-bound lifetimes,
643 printing e.g. `for<'a, 'b> `, and make those lifetimes visible
644 to the caller (via depth level, which the caller should reset). */
646 demangle_binder (struct rust_demangler
*rdm
)
648 uint64_t i
, bound_lifetimes
;
653 bound_lifetimes
= parse_opt_integer_62 (rdm
, 'G');
654 if (bound_lifetimes
> 0)
657 for (i
= 0; i
< bound_lifetimes
; i
++)
661 rdm
->bound_lifetime_depth
++;
662 print_lifetime_from_index (rdm
, 1);
669 demangle_path (struct rust_demangler
*rdm
, int in_value
)
672 int was_skipping_printing
;
673 size_t i
, backref
, old_next
;
675 struct rust_mangled_ident name
;
680 if (rdm
->recursion
!= RUST_NO_RECURSION_LIMIT
)
683 if (rdm
->recursion
> RUST_MAX_RECURSION_COUNT
)
684 /* FIXME: There ought to be a way to report
685 that the recursion limit has been reached. */
689 switch (tag
= next (rdm
))
692 dis
= parse_disambiguator (rdm
);
693 name
= parse_ident (rdm
);
695 print_ident (rdm
, name
);
699 print_uint64_hex (rdm
, dis
);
705 if (!ISLOWER (ns
) && !ISUPPER (ns
))
708 demangle_path (rdm
, in_value
);
710 dis
= parse_disambiguator (rdm
);
711 name
= parse_ident (rdm
);
715 /* Special namespaces, like closures and shims. */
726 print_str (rdm
, &ns
, 1);
728 if (name
.ascii
|| name
.punycode
)
731 print_ident (rdm
, name
);
734 print_uint64 (rdm
, dis
);
739 /* Implementation-specific/unspecified namespaces. */
741 if (name
.ascii
|| name
.punycode
)
744 print_ident (rdm
, name
);
750 /* Ignore the `impl`'s own path.*/
751 parse_disambiguator (rdm
);
752 was_skipping_printing
= rdm
->skipping_printing
;
753 rdm
->skipping_printing
= 1;
754 demangle_path (rdm
, in_value
);
755 rdm
->skipping_printing
= was_skipping_printing
;
763 demangle_path (rdm
, 0);
768 demangle_path (rdm
, in_value
);
772 for (i
= 0; !rdm
->errored
&& !eat (rdm
, 'E'); i
++)
776 demangle_generic_arg (rdm
);
781 backref
= parse_integer_62 (rdm
);
782 if (!rdm
->skipping_printing
)
784 old_next
= rdm
->next
;
786 demangle_path (rdm
, in_value
);
787 rdm
->next
= old_next
;
798 if (rdm
->recursion
!= RUST_NO_RECURSION_LIMIT
)
803 demangle_generic_arg (struct rust_demangler
*rdm
)
808 lt
= parse_integer_62 (rdm
);
809 print_lifetime_from_index (rdm
, lt
);
811 else if (eat (rdm
, 'K'))
812 demangle_const (rdm
);
818 basic_type (char tag
)
871 demangle_type (struct rust_demangler
*rdm
)
874 size_t i
, old_next
, backref
;
875 uint64_t lt
, old_bound_lifetime_depth
;
877 struct rust_mangled_ident abi
;
884 basic
= basic_type (tag
);
891 if (rdm
->recursion
!= RUST_NO_RECURSION_LIMIT
)
894 if (rdm
->recursion
> RUST_MAX_RECURSION_COUNT
)
895 /* FIXME: There ought to be a way to report
896 that the recursion limit has been reached. */
911 lt
= parse_integer_62 (rdm
);
914 print_lifetime_from_index (rdm
, lt
);
938 demangle_const (rdm
);
944 for (i
= 0; !rdm
->errored
&& !eat (rdm
, 'E'); i
++)
955 old_bound_lifetime_depth
= rdm
->bound_lifetime_depth
;
956 demangle_binder (rdm
);
970 abi
= parse_ident (rdm
);
971 if (!abi
.ascii
|| abi
.punycode
)
980 /* If the ABI had any `-`, they were replaced with `_`,
981 so the parts between `_` have to be re-joined with `-`. */
982 for (i
= 0; i
< abi
.ascii_len
; i
++)
984 if (abi
.ascii
[i
] == '_')
986 print_str (rdm
, abi
.ascii
, i
);
989 abi
.ascii_len
-= i
+ 1;
993 print_str (rdm
, abi
.ascii
, abi
.ascii_len
);
999 for (i
= 0; !rdm
->errored
&& !eat (rdm
, 'E'); i
++)
1003 demangle_type (rdm
);
1009 /* Skip printing the return type if it's 'u', i.e. `()`. */
1014 demangle_type (rdm
);
1017 /* Restore `bound_lifetime_depth` to outside the binder. */
1019 rdm
->bound_lifetime_depth
= old_bound_lifetime_depth
;
1024 old_bound_lifetime_depth
= rdm
->bound_lifetime_depth
;
1025 demangle_binder (rdm
);
1027 for (i
= 0; !rdm
->errored
&& !eat (rdm
, 'E'); i
++)
1031 demangle_dyn_trait (rdm
);
1034 /* Restore `bound_lifetime_depth` to outside the binder. */
1035 rdm
->bound_lifetime_depth
= old_bound_lifetime_depth
;
1037 if (!eat (rdm
, 'L'))
1042 lt
= parse_integer_62 (rdm
);
1046 print_lifetime_from_index (rdm
, lt
);
1050 backref
= parse_integer_62 (rdm
);
1051 if (!rdm
->skipping_printing
)
1053 old_next
= rdm
->next
;
1054 rdm
->next
= backref
;
1055 demangle_type (rdm
);
1056 rdm
->next
= old_next
;
1060 /* Go back to the tag, so `demangle_path` also sees it. */
1062 demangle_path (rdm
, 0);
1065 if (rdm
->recursion
!= RUST_NO_RECURSION_LIMIT
)
1069 /* A trait in a trait object may have some "existential projections"
1070 (i.e. associated type bindings) after it, which should be printed
1071 in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`.
1072 To this end, this method will keep the `<...>` of an 'I' path
1073 open, by omitting the `>`, and return `Ok(true)` in that case. */
1075 demangle_path_maybe_open_generics (struct rust_demangler
*rdm
)
1078 size_t i
, old_next
, backref
;
1087 backref
= parse_integer_62 (rdm
);
1088 if (!rdm
->skipping_printing
)
1090 old_next
= rdm
->next
;
1091 rdm
->next
= backref
;
1092 open
= demangle_path_maybe_open_generics (rdm
);
1093 rdm
->next
= old_next
;
1096 else if (eat (rdm
, 'I'))
1098 demangle_path (rdm
, 0);
1101 for (i
= 0; !rdm
->errored
&& !eat (rdm
, 'E'); i
++)
1105 demangle_generic_arg (rdm
);
1109 demangle_path (rdm
, 0);
1114 demangle_dyn_trait (struct rust_demangler
*rdm
)
1117 struct rust_mangled_ident name
;
1122 open
= demangle_path_maybe_open_generics (rdm
);
1124 while (eat (rdm
, 'p'))
1132 name
= parse_ident (rdm
);
1133 print_ident (rdm
, name
);
1135 demangle_type (rdm
);
1143 demangle_const (struct rust_demangler
*rdm
)
1146 size_t old_next
, backref
;
1153 backref
= parse_integer_62 (rdm
);
1154 if (!rdm
->skipping_printing
)
1156 old_next
= rdm
->next
;
1157 rdm
->next
= backref
;
1158 demangle_const (rdm
);
1159 rdm
->next
= old_next
;
1164 ty_tag
= next (rdm
);
1172 /* Unsigned integer types. */
1179 demangle_const_uint (rdm
);
1182 /* Signed integer types. */
1189 demangle_const_int (rdm
);
1194 demangle_const_bool (rdm
);
1199 demangle_const_char (rdm
);
1213 PRINT (basic_type (ty_tag
));
1218 demangle_const_uint (struct rust_demangler
*rdm
)
1226 hex_len
= parse_hex_nibbles (rdm
, &value
);
1230 /* Print anything that doesn't fit in `uint64_t` verbatim. */
1232 print_str (rdm
, rdm
->sym
+ (rdm
->next
- hex_len
), hex_len
);
1234 else if (hex_len
> 0)
1235 print_uint64 (rdm
, value
);
1241 demangle_const_int (struct rust_demangler
*rdm
)
1245 demangle_const_uint (rdm
);
1249 demangle_const_bool (struct rust_demangler
*rdm
)
1253 if (parse_hex_nibbles (rdm
, &value
) != 1)
1261 else if (value
== 1)
1268 demangle_const_char (struct rust_demangler
*rdm
)
1273 hex_len
= parse_hex_nibbles (rdm
, &value
);
1275 if (hex_len
== 0 || hex_len
> 8)
1281 /* Match Rust's character "debug" output as best as we can. */
1285 else if (value
== '\r')
1287 else if (value
== '\n')
1289 else if (value
> ' ' && value
< '~')
1291 /* Rust also considers many non-ASCII codepoints to be printable, but
1292 that logic is not easily ported to C. */
1294 print_str (rdm
, &c
, 1);
1299 print_uint64_hex (rdm
, value
);
1305 /* A legacy hash is the prefix "h" followed by 16 lowercase hex digits.
1306 The hex digits must contain at least 5 distinct digits. */
1308 is_legacy_prefixed_hash (struct rust_mangled_ident ident
)
1314 if (ident
.ascii_len
!= 17 || ident
.ascii
[0] != 'h')
1318 for (i
= 0; i
< 16; i
++)
1320 nibble
= decode_lower_hex_nibble (ident
.ascii
[1 + i
]);
1323 seen
|= (uint16_t)1 << nibble
;
1326 /* Count how many distinct digits were seen. */
1339 rust_demangle_callback (const char *mangled
, int options
,
1340 demangle_callbackref callback
, void *opaque
)
1343 struct rust_demangler rdm
;
1344 struct rust_mangled_ident ident
;
1349 rdm
.callback_opaque
= opaque
;
1350 rdm
.callback
= callback
;
1354 rdm
.skipping_printing
= 0;
1355 rdm
.verbose
= (options
& DMGL_VERBOSE
) != 0;
1357 rdm
.recursion
= (options
& DMGL_NO_RECURSE_LIMIT
) ? RUST_NO_RECURSION_LIMIT
: 0;
1358 rdm
.bound_lifetime_depth
= 0;
1360 /* Rust symbols always start with _R (v0) or _ZN (legacy). */
1361 if (rdm
.sym
[0] == '_' && rdm
.sym
[1] == 'R')
1363 else if (rdm
.sym
[0] == '_' && rdm
.sym
[1] == 'Z' && rdm
.sym
[2] == 'N')
1371 /* Paths (v0) always start with uppercase characters. */
1372 if (rdm
.version
!= -1 && !ISUPPER (rdm
.sym
[0]))
1375 /* Rust symbols (v0) use only [_0-9a-zA-Z] characters. */
1376 for (p
= rdm
.sym
; *p
; p
++)
1380 if (*p
== '_' || ISALNUM (*p
))
1383 /* Legacy Rust symbols can also contain [.:$] characters. */
1384 if (rdm
.version
== -1 && (*p
== '$' || *p
== '.' || *p
== ':'))
1390 /* Legacy Rust symbols need to be handled separately. */
1391 if (rdm
.version
== -1)
1393 /* Legacy Rust symbols always end with E. */
1394 if (!(rdm
.sym_len
> 0 && rdm
.sym
[rdm
.sym_len
- 1] == 'E'))
1398 /* Legacy Rust symbols also always end with a path segment
1399 that encodes a 16 hex digit hash, i.e. '17h[a-f0-9]{16}'.
1400 This early check, before any parse_ident calls, should
1401 quickly filter out most C++ symbols unrelated to Rust. */
1402 if (!(rdm
.sym_len
> 19
1403 && !memcmp (&rdm
.sym
[rdm
.sym_len
- 19], "17h", 3)))
1408 ident
= parse_ident (&rdm
);
1409 if (rdm
.errored
|| !ident
.ascii
)
1412 while (rdm
.next
< rdm
.sym_len
);
1414 /* The last path segment should be the hash. */
1415 if (!is_legacy_prefixed_hash (ident
))
1418 /* Reset the state for a second pass, to print the symbol. */
1420 if (!rdm
.verbose
&& rdm
.sym_len
> 19)
1422 /* Hide the last segment, containing the hash, if not verbose. */
1429 print_str (&rdm
, "::", 2);
1431 ident
= parse_ident (&rdm
);
1432 print_ident (&rdm
, ident
);
1434 while (rdm
.next
< rdm
.sym_len
);
1438 demangle_path (&rdm
, 1);
1440 /* Skip instantiating crate. */
1441 if (!rdm
.errored
&& rdm
.next
< rdm
.sym_len
)
1443 rdm
.skipping_printing
= 1;
1444 demangle_path (&rdm
, 0);
1447 /* It's an error to not reach the end. */
1448 rdm
.errored
|= rdm
.next
!= rdm
.sym_len
;
1451 return !rdm
.errored
;
1454 /* Growable string buffers. */
1464 str_buf_reserve (struct str_buf
*buf
, size_t extra
)
1466 size_t available
, min_new_cap
, new_cap
;
1469 /* Allocation failed before. */
1473 available
= buf
->cap
- buf
->len
;
1475 if (extra
<= available
)
1478 min_new_cap
= buf
->cap
+ (extra
- available
);
1480 /* Check for overflows. */
1481 if (min_new_cap
< buf
->cap
)
1492 /* Double capacity until sufficiently large. */
1493 while (new_cap
< min_new_cap
)
1497 /* Check for overflows. */
1498 if (new_cap
< buf
->cap
)
1505 new_ptr
= (char *)realloc (buf
->ptr
, new_cap
);
1506 if (new_ptr
== NULL
)
1522 str_buf_append (struct str_buf
*buf
, const char *data
, size_t len
)
1524 str_buf_reserve (buf
, len
);
1528 memcpy (buf
->ptr
+ buf
->len
, data
, len
);
1533 str_buf_demangle_callback (const char *data
, size_t len
, void *opaque
)
1535 str_buf_append ((struct str_buf
*)opaque
, data
, len
);
1539 rust_demangle (const char *mangled
, int options
)
1549 success
= rust_demangle_callback (mangled
, options
,
1550 str_buf_demangle_callback
, &out
);
1558 str_buf_append (&out
, "\0", 1);