Linux 5.1.15
[linux/fpc-iii.git] / tools / perf / util / demangle-java.c
blobe4c48675605319db28978d3827874416ad225eac
1 // SPDX-License-Identifier: GPL-2.0
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "util.h"
6 #include "debug.h"
7 #include "symbol.h"
9 #include "demangle-java.h"
11 #include "sane_ctype.h"
13 enum {
14 MODE_PREFIX = 0,
15 MODE_CLASS = 1,
16 MODE_FUNC = 2,
17 MODE_TYPE = 3,
18 MODE_CTYPE = 3, /* class arg */
21 #define BASE_ENT(c, n) [c - 'A']=n
22 static const char *base_types['Z' - 'A' + 1] = {
23 BASE_ENT('B', "byte" ),
24 BASE_ENT('C', "char" ),
25 BASE_ENT('D', "double" ),
26 BASE_ENT('F', "float" ),
27 BASE_ENT('I', "int" ),
28 BASE_ENT('J', "long" ),
29 BASE_ENT('S', "short" ),
30 BASE_ENT('Z', "bool" ),
34 * demangle Java symbol between str and end positions and stores
35 * up to maxlen characters into buf. The parser starts in mode.
37 * Use MODE_PREFIX to process entire prototype till end position
38 * Use MODE_TYPE to process return type if str starts on return type char
40 * Return:
41 * success: buf
42 * error : NULL
44 static char *
45 __demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode)
47 int rlen = 0;
48 int array = 0;
49 int narg = 0;
50 const char *q;
52 if (!end)
53 end = str + strlen(str);
55 for (q = str; q != end; q++) {
57 if (rlen == (maxlen - 1))
58 break;
60 switch (*q) {
61 case 'L':
62 if (mode == MODE_PREFIX || mode == MODE_CTYPE) {
63 if (mode == MODE_CTYPE) {
64 if (narg)
65 rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
66 narg++;
68 rlen += scnprintf(buf + rlen, maxlen - rlen, "class ");
69 if (mode == MODE_PREFIX)
70 mode = MODE_CLASS;
71 } else
72 buf[rlen++] = *q;
73 break;
74 case 'B':
75 case 'C':
76 case 'D':
77 case 'F':
78 case 'I':
79 case 'J':
80 case 'S':
81 case 'Z':
82 if (mode == MODE_TYPE) {
83 if (narg)
84 rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
85 rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']);
86 while (array--)
87 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
88 array = 0;
89 narg++;
90 } else
91 buf[rlen++] = *q;
92 break;
93 case 'V':
94 if (mode == MODE_TYPE) {
95 rlen += scnprintf(buf + rlen, maxlen - rlen, "void");
96 while (array--)
97 rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
98 array = 0;
99 } else
100 buf[rlen++] = *q;
101 break;
102 case '[':
103 if (mode != MODE_TYPE)
104 goto error;
105 array++;
106 break;
107 case '(':
108 if (mode != MODE_FUNC)
109 goto error;
110 buf[rlen++] = *q;
111 mode = MODE_TYPE;
112 break;
113 case ')':
114 if (mode != MODE_TYPE)
115 goto error;
116 buf[rlen++] = *q;
117 narg = 0;
118 break;
119 case ';':
120 if (mode != MODE_CLASS && mode != MODE_CTYPE)
121 goto error;
122 /* safe because at least one other char to process */
123 if (isalpha(*(q + 1)))
124 rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
125 if (mode == MODE_CLASS)
126 mode = MODE_FUNC;
127 else if (mode == MODE_CTYPE)
128 mode = MODE_TYPE;
129 break;
130 case '/':
131 if (mode != MODE_CLASS && mode != MODE_CTYPE)
132 goto error;
133 rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
134 break;
135 default :
136 buf[rlen++] = *q;
139 buf[rlen] = '\0';
140 return buf;
141 error:
142 return NULL;
146 * Demangle Java function signature (openJDK, not GCJ)
147 * input:
148 * str: string to parse. String is not modified
149 * flags: comobination of JAVA_DEMANGLE_* flags to modify demangling
150 * return:
151 * if input can be demangled, then a newly allocated string is returned.
152 * if input cannot be demangled, then NULL is returned
154 * Note: caller is responsible for freeing demangled string
156 char *
157 java_demangle_sym(const char *str, int flags)
159 char *buf, *ptr;
160 char *p;
161 size_t len, l1 = 0;
163 if (!str)
164 return NULL;
166 /* find start of retunr type */
167 p = strrchr(str, ')');
168 if (!p)
169 return NULL;
172 * expansion factor estimated to 3x
174 len = strlen(str) * 3 + 1;
175 buf = malloc(len);
176 if (!buf)
177 return NULL;
179 buf[0] = '\0';
180 if (!(flags & JAVA_DEMANGLE_NORET)) {
182 * get return type first
184 ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE);
185 if (!ptr)
186 goto error;
188 /* add space between return type and function prototype */
189 l1 = strlen(buf);
190 buf[l1++] = ' ';
193 /* process function up to return type */
194 ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX);
195 if (!ptr)
196 goto error;
198 return buf;
199 error:
200 free(buf);
201 return NULL;