8366 remove warlock leftovers from usr/src/cmd and usr/src/lib
[unleashed.git] / usr / src / cmd / sgs / libelf / misc / demangle.c
blob1397bfda9459fe04c33eb4deb81e3a8329951a39
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
27 * Copyright (c) 1998 by Sun Microsystems, Inc.
28 * All rights reserved.
31 #include <ctype.h>
32 #include <setjmp.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <thread.h>
36 #include "elf_dem.h"
37 #include "String.h"
38 #include "msg.h"
41 * The variable "hold" contains the pointer to the array initially
42 * handed to demangle. It is returned if it is not possible to
43 * demangle the string. NULL is returned if a memory allocation
44 * problem is encountered. Thus one can do the following:
46 * char *mn = "Some mangled name";
47 * char *dm = mangle(mn);
48 * if (dm == NULL)
49 * printf("allocation error\n");
50 * else if (dm == mn)
51 * printf("name could not be demangled\n");
52 * else
53 * printf("demangled name is: %s\n",dm);
55 static char *hold;
58 * this String is the working buffer for the demangle
59 * routine. A pointer into this String is returned
60 * from demangle when it is possible to demangle the
61 * String. For this reason, the pointer should not
62 * be saved between calls of demangle(), nor freed.
64 static String *s = 0;
66 static int
67 getint(char **c)
69 return (strtol(*c, c, 10));
73 * If a mangled name has a __
74 * that is not at the very beginning
75 * of the string, then this routine
76 * is called to demangle that part
77 * of the name. All overloaded functions,
78 * and class members fall into this category.
80 * c should start with two underscores followed by a non-zero digit or an F.
82 static char *
83 second(char *c)
85 int n;
86 if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2))
87 return (hold);
88 c += 2;
90 if (!(isdigit(*c) || *c == 'F'))
91 return (hold);
93 if (isdigit(*c)) {
94 /* a member */
95 n = getint(&c);
96 if (n == 0 || (int)strlen(c) < n)
97 return (hold);
98 s = prep_String(MSG_ORIG(MSG_STR_DBLCOL), s);
99 s = nprep_String(c, s, n);
100 c += n;
102 if (*c == 'F') {
103 /* an overloaded function */
104 switch (*++c) {
105 case '\0':
106 return (hold);
107 case 'v':
108 s = app_String(s, MSG_ORIG(MSG_STR_OPENCLOSEPAR));
109 break;
110 default:
111 if (demangle_doargs(&s, c) < 0)
112 return (hold);
115 return (PTR(s));
118 char *
119 demangle(char *c)
121 volatile int i = 0;
122 extern jmp_buf jbuf;
123 static mutex_t mlock = DEFAULTMUTEX;
125 (void) mutex_lock(&mlock);
127 if (setjmp(jbuf)) {
128 (void) mutex_unlock(&mlock);
129 return (0);
132 hold = c;
133 s = mk_String(s);
134 s = set_String(s, MSG_ORIG(MSG_STR_EMPTY));
136 if (c == 0 || *c == 0) {
137 c = hold;
138 (void) mutex_unlock(&mlock);
139 return (c);
142 if (strncmp(c, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) != 0) {
144 * If a name does not begin with a __
145 * but it does contain one, it is either
146 * a member or an overloaded function.
148 while (c[i] && strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2))
149 i++;
150 if (c[i]) {
151 /* Advance to first non-underscore */
152 while (c[i+2] == '_')
153 i++;
155 if (strncmp(c+i, MSG_ORIG(MSG_STR_DBLUNDBAR), 2) == 0) {
156 /* Copy the simple name */
157 s = napp_String(s, c, i);
158 /* Process the signature */
159 c = second(c+i);
160 (void) mutex_unlock(&mlock);
161 return (c);
162 } else {
163 c = hold;
164 (void) mutex_unlock(&mlock);
165 return (c);
167 } else {
168 const char *x;
169 int oplen;
171 c += 2;
174 * For automatic variables, or internal static
175 * variables, a __(number) is prepended to the
176 * name. If this is encountered, strip this off
177 * and return.
179 if (isdigit(*c)) {
180 while (isdigit(*c))
181 c++;
182 (void) mutex_unlock(&mlock);
183 return (c);
187 * Handle operator functions -- this
188 * automatically calls second, since
189 * all operator functions are overloaded.
191 if (x = findop(c, &oplen)) {
192 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_1));
193 s = app_String(s, x);
194 c += oplen;
195 c = second(c);
196 (void) mutex_unlock(&mlock);
197 return (c);
201 * Operator cast does not fit the mould
202 * of the other operators. Its type name
203 * is encoded. The cast function must
204 * take a void as an argument.
206 if (strncmp(c, MSG_ORIG(MSG_STR_OP), 2) == 0) {
207 int r;
208 s = app_String(s, MSG_ORIG(MSG_STR_OPERATOR_2));
209 c += 2;
210 r = demangle_doarg(&s, c);
211 if (r < 0) {
212 c = hold;
213 (void) mutex_unlock(&mlock);
214 return (c);
216 c += r;
217 c = second(c);
218 (void) mutex_unlock(&mlock);
219 return (c);
223 * Constructors and Destructors are also
224 * a special case of operator name. Note
225 * that the destructor, while overloaded,
226 * must always take the same arguments --
227 * none.
229 if ((*c == 'c' || *c == 'd') &&
230 strncmp(c+1, MSG_ORIG(MSG_STR_TDBLUNDBAR), 3) == 0) {
231 int n;
232 char *c2 = c+2;
233 char cx = c[0];
234 c += 4;
235 n = getint(&c);
236 if (n == 0) {
237 c = hold;
238 (void) mutex_unlock(&mlock);
239 return (c);
241 s = napp_String(s, c, n);
242 if (cx == 'd')
243 s = prep_String(MSG_ORIG(MSG_STR_TILDE), s);
244 c = second(c2);
245 (void) mutex_unlock(&mlock);
246 return (c);
248 c = hold;
249 (void) mutex_unlock(&mlock);
250 return (c);