1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2001-2002, 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 2, 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. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, USA. *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
31 ****************************************************************************/
38 #define PARMS(ARGS) ARGS
42 #include "adadecode.h"
44 static void add_verbose PARAMS ((const char *, char *));
45 static int has_prefix PARAMS ((char *, const char *));
46 static int has_suffix PARAMS ((char *, const char *));
48 /* Set to nonzero if we have written any verbose info. */
49 static int verbose_info;
51 /* Add TEXT to end of ADA_NAME, putting a leading " (" or ", ", depending
54 static void add_verbose (text, ada_name)
58 strcat (ada_name, verbose_info ? ", " : " (");
59 strcat (ada_name, text);
64 /* Returns 1 if NAME starts with PREFIX. */
67 has_prefix (name, prefix)
71 return strncmp (name, prefix, strlen (prefix)) == 0;
74 /* Returns 1 if NAME ends with SUFFIX. */
77 has_suffix (name, suffix)
81 int nlen = strlen (name);
82 int slen = strlen (suffix);
84 return nlen > slen && strncmp (name + nlen - slen, suffix, slen) == 0;
87 /* This function will return the Ada name from the encoded form.
88 The Ada coding is done in exp_dbug.ads and this is the inverse function.
89 see exp_dbug.ads for full encoding rules, a short description is added
90 below. Right now only objects and routines are handled. There is no support
93 CODED_NAME is the encoded entity name.
95 ADA_NAME is a pointer to a buffer, it will receive the Ada name. A safe
96 size for this buffer is: strlen (coded_name) * 2 + 60. (60 is for the
99 VERBOSE is nonzero if more information about the entity is to be
100 added at the end of the Ada name and surrounded by ( and ).
102 Coded name Ada name verbose info
103 ---------------------------------------------------------------------
104 _ada_xyz xyz library level
106 x__yTKB x.y task body
108 x__yX x.y body nested
109 x__yXb x.y body nested
111 x__y$2 x.y overloaded
112 x__y__3 x.y overloaded
134 __gnat_decode (coded_name, ada_name, verbose)
135 const char *coded_name;
145 /* Copy the coded name into the ada name string, the rest of the code will
146 just replace or add characters into the ada_name. */
147 strcpy (ada_name, coded_name);
149 /* Check for library level subprogram. */
150 if (has_prefix (ada_name, "_ada_"))
152 strcpy (ada_name, ada_name + 5);
156 /* Check for task body. */
157 if (has_suffix (ada_name, "TKB"))
159 ada_name[strlen (ada_name) - 3] = '\0';
163 if (has_suffix (ada_name, "B"))
165 ada_name[strlen (ada_name) - 1] = '\0';
169 /* Check for body-nested entity: X[bn] */
170 if (has_suffix (ada_name, "X"))
172 ada_name[strlen (ada_name) - 1] = '\0';
176 if (has_suffix (ada_name, "Xb"))
178 ada_name[strlen (ada_name) - 2] = '\0';
182 if (has_suffix (ada_name, "Xn"))
184 ada_name[strlen (ada_name) - 2] = '\0';
188 /* Change instance of TK__ (object declared inside a task) to __. */
192 while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
194 strcpy (tktoken, tktoken + 2);
199 /* Check for overloading: name terminated by $nn or __nn. */
201 int len = strlen (ada_name);
205 while (isdigit ((int) ada_name[(int) len - 1 - n_digits]))
208 /* Check if we have $ or __ before digits. */
209 if (ada_name[len - 1 - n_digits] == '$')
211 ada_name[len - 1 - n_digits] = '\0';
214 else if (ada_name[len - 1 - n_digits] == '_'
215 && ada_name[len - 1 - n_digits - 1] == '_')
217 ada_name[len - 1 - n_digits - 1] = '\0';
222 /* Change all "__" to ".". */
224 int len = strlen (ada_name);
229 if (ada_name[k] == '_' && ada_name[k+1] == '_')
232 strcpy (ada_name + k + 1, ada_name + k + 2);
239 /* Checks for operator name. */
241 const char *trans_table[][2]
242 = {{"Oabs", "\"abs\""}, {"Oand", "\"and\""}, {"Omod", "\"mod\""},
243 {"Onot", "\"not\""}, {"Oor", "\"or\""}, {"Orem", "\"rem\""},
244 {"Oxor", "\"xor\""}, {"Oeq", "\"=\""}, {"One", "\"/=\""},
245 {"Olt", "\"<\""}, {"Ole", "\"<=\""}, {"Ogt", "\">\""},
246 {"Oge", "\">=\""}, {"Oadd", "\"+\""}, {"Osubtract", "\"-\""},
247 {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
248 {"Oexpon", "\"**\""}, {NULL, NULL} };
255 if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
257 int codedlen = strlen (trans_table[k][0]);
258 int oplen = strlen (trans_table[k][1]);
260 if (codedlen > oplen)
261 /* We shrink the space. */
262 strcpy (optoken, optoken + codedlen - oplen);
263 else if (oplen > codedlen)
265 /* We need more space. */
266 int len = strlen (ada_name);
267 int space = oplen - codedlen;
268 int num_to_move = &ada_name[len] - optoken;
271 for (t = 0; t < num_to_move; t++)
272 ada_name[len + space - t - 1] = ada_name[len - t - 1];
275 /* Write symbol in the space. */
276 strncpy (optoken, trans_table[k][1], oplen);
281 /* Check for table's ending. */
282 if (trans_table[k][0] == NULL)
287 /* If verbose mode is on, we add some information to the Ada name. */
291 add_verbose ("overloaded", ada_name);
294 add_verbose ("library level", ada_name);
297 add_verbose ("body nested", ada_name);
300 add_verbose ("in task", ada_name);
303 add_verbose ("task body", ada_name);
305 if (verbose_info == 1)
306 strcat (ada_name, ")");
311 ada_demangle (coded_name)
312 const char *coded_name;
316 __gnat_decode (coded_name, ada_name, 0);
317 return xstrdup (ada_name);