annotate libiberty/rust-demangle.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Demangler for the Rust programming language
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2016-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Written by David Tolnay (dtolnay@gmail.com).
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of the libiberty library.
kono
parents:
diff changeset
6 Libiberty is free software; you can redistribute it and/or
kono
parents:
diff changeset
7 modify it under the terms of the GNU Library General Public
kono
parents:
diff changeset
8 License as published by the Free Software Foundation; either
kono
parents:
diff changeset
9 version 2 of the License, or (at your option) any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 In addition to the permissions in the GNU Library General Public
kono
parents:
diff changeset
12 License, the Free Software Foundation gives you unlimited permission
kono
parents:
diff changeset
13 to link the compiled version of this file into combinations with other
kono
parents:
diff changeset
14 programs, and to distribute those combinations without any restriction
kono
parents:
diff changeset
15 coming from the use of this file. (The Library Public License
kono
parents:
diff changeset
16 restrictions do apply in other respects; for example, they cover
kono
parents:
diff changeset
17 modification of the file, and distribution when not linked into a
kono
parents:
diff changeset
18 combined executable.)
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 Libiberty is distributed in the hope that it will be useful,
kono
parents:
diff changeset
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kono
parents:
diff changeset
23 Library General Public License for more details.
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 You should have received a copy of the GNU Library General Public
kono
parents:
diff changeset
26 License along with libiberty; see the file COPYING.LIB.
kono
parents:
diff changeset
27 If not, see <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 #ifdef HAVE_CONFIG_H
kono
parents:
diff changeset
31 #include "config.h"
kono
parents:
diff changeset
32 #endif
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 #include "safe-ctype.h"
kono
parents:
diff changeset
35
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
36 #include <inttypes.h>
111
kono
parents:
diff changeset
37 #include <sys/types.h>
kono
parents:
diff changeset
38 #include <string.h>
kono
parents:
diff changeset
39 #include <stdio.h>
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
40 #include <stdlib.h>
111
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 #ifdef HAVE_STRING_H
kono
parents:
diff changeset
43 #include <string.h>
kono
parents:
diff changeset
44 #else
kono
parents:
diff changeset
45 extern size_t strlen(const char *s);
kono
parents:
diff changeset
46 extern int strncmp(const char *s1, const char *s2, size_t n);
kono
parents:
diff changeset
47 extern void *memset(void *s, int c, size_t n);
kono
parents:
diff changeset
48 #endif
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 #include <demangle.h>
kono
parents:
diff changeset
51 #include "libiberty.h"
kono
parents:
diff changeset
52
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
53 struct rust_demangler
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
54 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
55 const char *sym;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
56 size_t sym_len;
111
kono
parents:
diff changeset
57
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
58 void *callback_opaque;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
59 demangle_callbackref callback;
111
kono
parents:
diff changeset
60
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
61 /* Position of the next character to read from the symbol. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
62 size_t next;
111
kono
parents:
diff changeset
63
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
64 /* Non-zero if any error occurred. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
65 int errored;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
66
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
67 /* Non-zero if printing should be verbose (e.g. include hashes). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
68 int verbose;
111
kono
parents:
diff changeset
69
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
70 /* Rust mangling version, with legacy mangling being -1. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
71 int version;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
72 };
111
kono
parents:
diff changeset
73
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
74 /* Parsing functions. */
111
kono
parents:
diff changeset
75
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
76 static char
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
77 peek (const struct rust_demangler *rdm)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
78 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
79 if (rdm->next < rdm->sym_len)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
80 return rdm->sym[rdm->next];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
81 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
82 }
111
kono
parents:
diff changeset
83
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
84 static char
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
85 next (struct rust_demangler *rdm)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
86 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
87 char c = peek (rdm);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
88 if (!c)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
89 rdm->errored = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
90 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
91 rdm->next++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
92 return c;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
93 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
94
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
95 struct rust_mangled_ident
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
96 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
97 /* ASCII part of the identifier. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
98 const char *ascii;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
99 size_t ascii_len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
100 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
101
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
102 static struct rust_mangled_ident
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
103 parse_ident (struct rust_demangler *rdm)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
104 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
105 char c;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
106 size_t start, len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
107 struct rust_mangled_ident ident;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
108
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
109 ident.ascii = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
110 ident.ascii_len = 0;
111
kono
parents:
diff changeset
111
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
112 c = next (rdm);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
113 if (!ISDIGIT (c))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
114 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
115 rdm->errored = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
116 return ident;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
117 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
118 len = c - '0';
111
kono
parents:
diff changeset
119
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
120 if (c != '0')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
121 while (ISDIGIT (peek (rdm)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
122 len = len * 10 + (next (rdm) - '0');
111
kono
parents:
diff changeset
123
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
124 start = rdm->next;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
125 rdm->next += len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
126 /* Check for overflows. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
127 if ((start > rdm->next) || (rdm->next > rdm->sym_len))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
128 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
129 rdm->errored = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
130 return ident;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
131 }
111
kono
parents:
diff changeset
132
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
133 ident.ascii = rdm->sym + start;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
134 ident.ascii_len = len;
111
kono
parents:
diff changeset
135
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
136 if (ident.ascii_len == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
137 ident.ascii = NULL;
111
kono
parents:
diff changeset
138
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
139 return ident;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
140 }
111
kono
parents:
diff changeset
141
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
142 /* Printing functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
143
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
144 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
145 print_str (struct rust_demangler *rdm, const char *data, size_t len)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
146 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
147 if (!rdm->errored)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
148 rdm->callback (data, len, rdm->callback_opaque);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
149 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
150
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
151 #define PRINT(s) print_str (rdm, s, strlen (s))
111
kono
parents:
diff changeset
152
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
153 /* Return a 0x0-0xf value if the char is 0-9a-f, and -1 otherwise. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
154 static int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
155 decode_lower_hex_nibble (char nibble)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
156 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
157 if ('0' <= nibble && nibble <= '9')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
158 return nibble - '0';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
159 if ('a' <= nibble && nibble <= 'f')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
160 return 0xa + (nibble - 'a');
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
161 return -1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
162 }
111
kono
parents:
diff changeset
163
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
164 /* Return the unescaped character for a "$...$" escape, or 0 if invalid. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
165 static char
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
166 decode_legacy_escape (const char *e, size_t len, size_t *out_len)
111
kono
parents:
diff changeset
167 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
168 char c = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
169 size_t escape_len = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
170 int lo_nibble = -1, hi_nibble = -1;
111
kono
parents:
diff changeset
171
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
172 if (len < 3 || e[0] != '$')
111
kono
parents:
diff changeset
173 return 0;
kono
parents:
diff changeset
174
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
175 e++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
176 len--;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
177
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
178 if (e[0] == 'C')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
179 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
180 escape_len = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
181
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
182 c = ',';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
183 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
184 else if (len > 2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
185 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
186 escape_len = 2;
111
kono
parents:
diff changeset
187
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
188 if (e[0] == 'S' && e[1] == 'P')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
189 c = '@';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
190 else if (e[0] == 'B' && e[1] == 'P')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
191 c = '*';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
192 else if (e[0] == 'R' && e[1] == 'F')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
193 c = '&';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
194 else if (e[0] == 'L' && e[1] == 'T')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
195 c = '<';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
196 else if (e[0] == 'G' && e[1] == 'T')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
197 c = '>';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
198 else if (e[0] == 'L' && e[1] == 'P')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
199 c = '(';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
200 else if (e[0] == 'R' && e[1] == 'P')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
201 c = ')';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
202 else if (e[0] == 'u' && len > 3)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
203 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
204 escape_len = 3;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
205
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
206 hi_nibble = decode_lower_hex_nibble (e[1]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
207 if (hi_nibble < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
208 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
209 lo_nibble = decode_lower_hex_nibble (e[2]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
210 if (lo_nibble < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
211 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
212
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
213 /* Only allow non-control ASCII characters. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
214 if (hi_nibble > 7)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
215 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
216 c = (hi_nibble << 4) | lo_nibble;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
217 if (c < 0x20)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
218 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
219 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
220 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
221
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
222 if (!c || len <= escape_len || e[escape_len] != '$')
111
kono
parents:
diff changeset
223 return 0;
kono
parents:
diff changeset
224
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
225 *out_len = 2 + escape_len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
226 return c;
111
kono
parents:
diff changeset
227 }
kono
parents:
diff changeset
228
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
229 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
230 print_ident (struct rust_demangler *rdm, struct rust_mangled_ident ident)
111
kono
parents:
diff changeset
231 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
232 char unescaped;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
233 size_t len;
111
kono
parents:
diff changeset
234
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
235 if (rdm->errored)
111
kono
parents:
diff changeset
236 return;
kono
parents:
diff changeset
237
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
238 if (rdm->version == -1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
239 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
240 /* Ignore leading underscores preceding escape sequences.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
241 The mangler inserts an underscore to make sure the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
242 identifier begins with a XID_Start character. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
243 if (ident.ascii_len >= 2 && ident.ascii[0] == '_'
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
244 && ident.ascii[1] == '$')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
245 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
246 ident.ascii++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
247 ident.ascii_len--;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
248 }
111
kono
parents:
diff changeset
249
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
250 while (ident.ascii_len > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
251 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
252 /* Handle legacy escape sequences ("$...$", ".." or "."). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
253 if (ident.ascii[0] == '$')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
254 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
255 unescaped
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
256 = decode_legacy_escape (ident.ascii, ident.ascii_len, &len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
257 if (unescaped)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
258 print_str (rdm, &unescaped, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
259 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
260 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
261 /* Unexpected escape sequence, print the rest verbatim. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
262 print_str (rdm, ident.ascii, ident.ascii_len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
263 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
264 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
265 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
266 else if (ident.ascii[0] == '.')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
267 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
268 if (ident.ascii_len >= 2 && ident.ascii[1] == '.')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
269 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
270 /* ".." becomes "::" */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
271 PRINT ("::");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
272 len = 2;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
273 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
274 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
275 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
276 /* "." becomes "-" */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
277 PRINT ("-");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
278 len = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
279 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
280 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
281 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
282 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
283 /* Print everything before the next escape sequence, at once. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
284 for (len = 0; len < ident.ascii_len; len++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
285 if (ident.ascii[len] == '$' || ident.ascii[len] == '.')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
286 break;
111
kono
parents:
diff changeset
287
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
288 print_str (rdm, ident.ascii, len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
289 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
290
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
291 ident.ascii += len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
292 ident.ascii_len -= len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
293 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
294
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
295 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
296 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
297 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
298
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
299 /* A legacy hash is the prefix "h" followed by 16 lowercase hex digits.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
300 The hex digits must contain at least 5 distinct digits. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
301 static int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
302 is_legacy_prefixed_hash (struct rust_mangled_ident ident)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
303 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
304 uint16_t seen;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
305 int nibble;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
306 size_t i, count;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
307
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
308 if (ident.ascii_len != 17 || ident.ascii[0] != 'h')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
309 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
310
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
311 seen = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
312 for (i = 0; i < 16; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
313 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
314 nibble = decode_lower_hex_nibble (ident.ascii[1 + i]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
315 if (nibble < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
316 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
317 seen |= (uint16_t)1 << nibble;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
318 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
319
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
320 /* Count how many distinct digits were seen. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
321 count = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
322 while (seen)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
323 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
324 if (seen & 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
325 count++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
326 seen >>= 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
327 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
328
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
329 return count >= 5;
111
kono
parents:
diff changeset
330 }
kono
parents:
diff changeset
331
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
332 int
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
333 rust_demangle_callback (const char *mangled, int options,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
334 demangle_callbackref callback, void *opaque)
111
kono
parents:
diff changeset
335 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
336 const char *p;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
337 struct rust_demangler rdm;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
338 struct rust_mangled_ident ident;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
339
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
340 rdm.sym = mangled;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
341 rdm.sym_len = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
342
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
343 rdm.callback_opaque = opaque;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
344 rdm.callback = callback;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
345
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
346 rdm.next = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
347 rdm.errored = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
348 rdm.verbose = (options & DMGL_VERBOSE) != 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
349 rdm.version = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
350
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
351 /* Rust symbols always start with _ZN (legacy). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
352 if (rdm.sym[0] == '_' && rdm.sym[1] == 'Z' && rdm.sym[2] == 'N')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
353 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
354 rdm.sym += 3;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
355 rdm.version = -1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
356 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
357 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
358 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
359
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
360 /* Legacy Rust symbols use only [_0-9a-zA-Z.:$] characters. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
361 for (p = rdm.sym; *p; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
362 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
363 rdm.sym_len++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
364
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
365 if (*p == '_' || ISALNUM (*p))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
366 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
367
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
368 if (rdm.version == -1 && (*p == '$' || *p == '.' || *p == ':'))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
369 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
370
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
371 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
372 }
111
kono
parents:
diff changeset
373
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
374 /* Legacy Rust symbols need to be handled separately. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
375 if (rdm.version == -1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
376 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
377 /* Legacy Rust symbols always end with E. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
378 if (!(rdm.sym_len > 0 && rdm.sym[rdm.sym_len - 1] == 'E'))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
379 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
380 rdm.sym_len--;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
381
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
382 /* Legacy Rust symbols also always end with a path segment
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
383 that encodes a 16 hex digit hash, i.e. '17h[a-f0-9]{16}'.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
384 This early check, before any parse_ident calls, should
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
385 quickly filter out most C++ symbols unrelated to Rust. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
386 if (!(rdm.sym_len > 19
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
387 && !memcmp (&rdm.sym[rdm.sym_len - 19], "17h", 3)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
388 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
389
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
390 do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
391 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
392 ident = parse_ident (&rdm);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
393 if (rdm.errored || !ident.ascii)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
394 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
395 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
396 while (rdm.next < rdm.sym_len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
397
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
398 /* The last path segment should be the hash. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
399 if (!is_legacy_prefixed_hash (ident))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
400 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
401
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
402 /* Reset the state for a second pass, to print the symbol. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
403 rdm.next = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
404 if (!rdm.verbose && rdm.sym_len > 19)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
405 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
406 /* Hide the last segment, containing the hash, if not verbose. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
407 rdm.sym_len -= 19;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
408 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
409
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
410 do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
411 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
412 if (rdm.next > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
413 print_str (&rdm, "::", 2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
414
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
415 ident = parse_ident (&rdm);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
416 print_ident (&rdm, ident);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
417 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
418 while (rdm.next < rdm.sym_len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
419 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
420 else
111
kono
parents:
diff changeset
421 return 0;
kono
parents:
diff changeset
422
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
423 return !rdm.errored;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
424 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
425
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
426 /* Growable string buffers. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
427 struct str_buf
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
428 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
429 char *ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
430 size_t len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
431 size_t cap;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
432 int errored;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
433 };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
434
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
435 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
436 str_buf_reserve (struct str_buf *buf, size_t extra)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
437 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
438 size_t available, min_new_cap, new_cap;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
439 char *new_ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
440
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
441 /* Allocation failed before. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
442 if (buf->errored)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
443 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
444
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
445 available = buf->cap - buf->len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
446
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
447 if (extra <= available)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
448 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
449
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
450 min_new_cap = buf->cap + (extra - available);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
451
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
452 /* Check for overflows. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
453 if (min_new_cap < buf->cap)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
454 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
455 buf->errored = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
456 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
457 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
458
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
459 new_cap = buf->cap;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
460
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
461 if (new_cap == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
462 new_cap = 4;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
463
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
464 /* Double capacity until sufficiently large. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
465 while (new_cap < min_new_cap)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
466 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
467 new_cap *= 2;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
468
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
469 /* Check for overflows. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
470 if (new_cap < buf->cap)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
471 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
472 buf->errored = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
473 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
474 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
475 }
111
kono
parents:
diff changeset
476
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
477 new_ptr = (char *)realloc (buf->ptr, new_cap);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
478 if (new_ptr == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
479 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
480 free (buf->ptr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
481 buf->ptr = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
482 buf->len = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
483 buf->cap = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
484 buf->errored = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
485 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
486 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
487 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
488 buf->ptr = new_ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
489 buf->cap = new_cap;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
490 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
491 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
492
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
493 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
494 str_buf_append (struct str_buf *buf, const char *data, size_t len)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
495 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
496 str_buf_reserve (buf, len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
497 if (buf->errored)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
498 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
499
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
500 memcpy (buf->ptr + buf->len, data, len);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
501 buf->len += len;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
502 }
111
kono
parents:
diff changeset
503
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
504 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
505 str_buf_demangle_callback (const char *data, size_t len, void *opaque)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
506 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
507 str_buf_append ((struct str_buf *)opaque, data, len);
111
kono
parents:
diff changeset
508 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
509
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
510 char *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 rust_demangle (const char *mangled, int options)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
512 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
513 struct str_buf out;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
514 int success;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
515
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516 out.ptr = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
517 out.len = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
518 out.cap = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
519 out.errored = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
520
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
521 success = rust_demangle_callback (mangled, options,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
522 str_buf_demangle_callback, &out);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
523
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 if (!success)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
525 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
526 free (out.ptr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
527 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
528 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
529
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
530 str_buf_append (&out, "\0", 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
531 return out.ptr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
532 }