1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2001-2009, Free Software Foundation, Inc. *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 3, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
22 * You should have received a copy of the GNU General Public License and *
23 * a copy of the GCC Runtime Library Exception along with this program; *
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
25 * <http://www.gnu.org/licenses/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
39 #define ISDIGIT(c) isdigit(c)
40 #define PARMS(ARGS) ARGS
43 #include "adadecode.h"
45 static void add_verbose (const char *, char *);
46 static int has_prefix (const char *, const char *);
47 static int has_suffix (const char *, const char *);
49 /* This is a safe version of strcpy that can be used with overlapped
50 pointers. Does nothing if s2 <= s1. */
51 static void ostrcpy (char *s1, char *s2);
53 /* Set to nonzero if we have written any verbose info. */
54 static int verbose_info;
56 /* Add TEXT to end of ADA_NAME, putting a leading " (" or ", ", depending
59 static void add_verbose (const char *text, char *ada_name)
61 strcat (ada_name, verbose_info ? ", " : " (");
62 strcat (ada_name, text);
67 /* Returns 1 if NAME starts with PREFIX. */
70 has_prefix (const char *name, const char *prefix)
72 return strncmp (name, prefix, strlen (prefix)) == 0;
75 /* Returns 1 if NAME ends with SUFFIX. */
78 has_suffix (const char *name, const char *suffix)
80 int nlen = strlen (name);
81 int slen = strlen (suffix);
83 return nlen > slen && strncmp (name + nlen - slen, suffix, slen) == 0;
86 /* Safe overlapped pointers version of strcpy. */
89 ostrcpy (char *s1, char *s2)
93 while (*s2) *s1++ = *s2++;
98 /* This function will return the Ada name from the encoded form.
99 The Ada coding is done in exp_dbug.ads and this is the inverse function.
100 see exp_dbug.ads for full encoding rules, a short description is added
101 below. Right now only objects and routines are handled. Ada types are
102 stripped of their encodings.
104 CODED_NAME is the encoded entity name.
106 ADA_NAME is a pointer to a buffer, it will receive the Ada name. A safe
107 size for this buffer is: strlen (coded_name) * 2 + 60. (60 is for the
108 verbose information).
110 VERBOSE is nonzero if more information about the entity is to be
111 added at the end of the Ada name and surrounded by ( and ).
113 Coded name Ada name verbose info
114 ---------------------------------------------------------------------
115 _ada_xyz xyz library level
117 x__yTKB x.y task body
119 x__yX x.y body nested
120 x__yXb x.y body nested
122 x__y$2 x.y overloaded
123 x__y__3 x.y overloaded
145 __gnat_decode (const char *coded_name, char *ada_name, int verbose)
153 /* Check for library level subprogram. */
154 if (has_prefix (coded_name, "_ada_"))
156 strcpy (ada_name, coded_name + 5);
160 strcpy (ada_name, coded_name);
162 /* Check for the first triple underscore in the name. This indicates
163 that the name represents a type with encodings; in this case, we
164 need to strip the encodings. */
168 if ((encodings = (char *) strstr (ada_name, "___")) != NULL)
174 /* Check for task body. */
175 if (has_suffix (ada_name, "TKB"))
177 ada_name[strlen (ada_name) - 3] = '\0';
181 if (has_suffix (ada_name, "B"))
183 ada_name[strlen (ada_name) - 1] = '\0';
187 /* Check for body-nested entity: X[bn] */
188 if (has_suffix (ada_name, "X"))
190 ada_name[strlen (ada_name) - 1] = '\0';
194 if (has_suffix (ada_name, "Xb"))
196 ada_name[strlen (ada_name) - 2] = '\0';
200 if (has_suffix (ada_name, "Xn"))
202 ada_name[strlen (ada_name) - 2] = '\0';
206 /* Change instance of TK__ (object declared inside a task) to __. */
210 while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
212 ostrcpy (tktoken, tktoken + 2);
217 /* Check for overloading: name terminated by $nn or __nn. */
219 int len = strlen (ada_name);
223 while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
226 /* Check if we have $ or __ before digits. */
227 if (ada_name[len - 1 - n_digits] == '$')
229 ada_name[len - 1 - n_digits] = '\0';
232 else if (ada_name[len - 1 - n_digits] == '_'
233 && ada_name[len - 1 - n_digits - 1] == '_')
235 ada_name[len - 1 - n_digits - 1] = '\0';
240 /* Change all "__" to ".". */
242 int len = strlen (ada_name);
247 if (ada_name[k] == '_' && ada_name[k+1] == '_')
250 ostrcpy (ada_name + k + 1, ada_name + k + 2);
257 /* Checks for operator name. */
259 const char *trans_table[][2]
260 = {{"Oabs", "\"abs\""}, {"Oand", "\"and\""}, {"Omod", "\"mod\""},
261 {"Onot", "\"not\""}, {"Oor", "\"or\""}, {"Orem", "\"rem\""},
262 {"Oxor", "\"xor\""}, {"Oeq", "\"=\""}, {"One", "\"/=\""},
263 {"Olt", "\"<\""}, {"Ole", "\"<=\""}, {"Ogt", "\">\""},
264 {"Oge", "\">=\""}, {"Oadd", "\"+\""}, {"Osubtract", "\"-\""},
265 {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
266 {"Oexpon", "\"**\""}, {NULL, NULL} };
273 if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
275 int codedlen = strlen (trans_table[k][0]);
276 int oplen = strlen (trans_table[k][1]);
278 if (codedlen > oplen)
279 /* We shrink the space. */
280 ostrcpy (optoken, optoken + codedlen - oplen);
281 else if (oplen > codedlen)
283 /* We need more space. */
284 int len = strlen (ada_name);
285 int space = oplen - codedlen;
286 int num_to_move = &ada_name[len] - optoken;
289 for (t = 0; t < num_to_move; t++)
290 ada_name[len + space - t - 1] = ada_name[len - t - 1];
293 /* Write symbol in the space. */
294 strncpy (optoken, trans_table[k][1], oplen);
299 /* Check for table's ending. */
300 if (trans_table[k][0] == NULL)
305 /* If verbose mode is on, we add some information to the Ada name. */
309 add_verbose ("overloaded", ada_name);
312 add_verbose ("library level", ada_name);
315 add_verbose ("body nested", ada_name);
318 add_verbose ("in task", ada_name);
321 add_verbose ("task body", ada_name);
323 if (verbose_info == 1)
324 strcat (ada_name, ")");
330 ada_demangle (const char *coded_name)
334 __gnat_decode (coded_name, ada_name, 0);
335 return xstrdup (ada_name);
340 get_encoding (const char *coded_name, char *encoding)
342 char * dest_index = encoding;
347 /* The heuristics is the following: we assume that the first triple
348 underscore in an encoded name indicates the beginning of the
349 first encoding, and that subsequent triple underscores indicate
350 the next encodings. We assume that the encodings are always at the
351 end of encoded names. */
353 for (p = coded_name; *p != '\0'; p++)
364 dest_index = dest_index - 2;