Linux Audio

Check our new training course

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