1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2001-2003, 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 ****************************************************************************/
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. There is no support
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 task body. */
163 if (has_suffix (ada_name
, "TKB"))
165 ada_name
[strlen (ada_name
) - 3] = '\0';
169 if (has_suffix (ada_name
, "B"))
171 ada_name
[strlen (ada_name
) - 1] = '\0';
175 /* Check for body-nested entity: X[bn] */
176 if (has_suffix (ada_name
, "X"))
178 ada_name
[strlen (ada_name
) - 1] = '\0';
182 if (has_suffix (ada_name
, "Xb"))
184 ada_name
[strlen (ada_name
) - 2] = '\0';
188 if (has_suffix (ada_name
, "Xn"))
190 ada_name
[strlen (ada_name
) - 2] = '\0';
194 /* Change instance of TK__ (object declared inside a task) to __. */
198 while ((tktoken
= (char *) strstr (ada_name
, "TK__")) != NULL
)
200 ostrcpy (tktoken
, tktoken
+ 2);
205 /* Check for overloading: name terminated by $nn or __nn. */
207 int len
= strlen (ada_name
);
211 while (ISDIGIT ((int) ada_name
[(int) len
- 1 - n_digits
]))
214 /* Check if we have $ or __ before digits. */
215 if (ada_name
[len
- 1 - n_digits
] == '$')
217 ada_name
[len
- 1 - n_digits
] = '\0';
220 else if (ada_name
[len
- 1 - n_digits
] == '_'
221 && ada_name
[len
- 1 - n_digits
- 1] == '_')
223 ada_name
[len
- 1 - n_digits
- 1] = '\0';
228 /* Change all "__" to ".". */
230 int len
= strlen (ada_name
);
235 if (ada_name
[k
] == '_' && ada_name
[k
+1] == '_')
238 ostrcpy (ada_name
+ k
+ 1, ada_name
+ k
+ 2);
245 /* Checks for operator name. */
247 const char *trans_table
[][2]
248 = {{"Oabs", "\"abs\""}, {"Oand", "\"and\""}, {"Omod", "\"mod\""},
249 {"Onot", "\"not\""}, {"Oor", "\"or\""}, {"Orem", "\"rem\""},
250 {"Oxor", "\"xor\""}, {"Oeq", "\"=\""}, {"One", "\"/=\""},
251 {"Olt", "\"<\""}, {"Ole", "\"<=\""}, {"Ogt", "\">\""},
252 {"Oge", "\">=\""}, {"Oadd", "\"+\""}, {"Osubtract", "\"-\""},
253 {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
254 {"Oexpon", "\"**\""}, {NULL
, NULL
} };
261 if ((optoken
= (char *) strstr (ada_name
, trans_table
[k
][0])) != NULL
)
263 int codedlen
= strlen (trans_table
[k
][0]);
264 int oplen
= strlen (trans_table
[k
][1]);
266 if (codedlen
> oplen
)
267 /* We shrink the space. */
268 ostrcpy (optoken
, optoken
+ codedlen
- oplen
);
269 else if (oplen
> codedlen
)
271 /* We need more space. */
272 int len
= strlen (ada_name
);
273 int space
= oplen
- codedlen
;
274 int num_to_move
= &ada_name
[len
] - optoken
;
277 for (t
= 0; t
< num_to_move
; t
++)
278 ada_name
[len
+ space
- t
- 1] = ada_name
[len
- t
- 1];
281 /* Write symbol in the space. */
282 strncpy (optoken
, trans_table
[k
][1], oplen
);
287 /* Check for table's ending. */
288 if (trans_table
[k
][0] == NULL
)
293 /* If verbose mode is on, we add some information to the Ada name. */
297 add_verbose ("overloaded", ada_name
);
300 add_verbose ("library level", ada_name
);
303 add_verbose ("body nested", ada_name
);
306 add_verbose ("in task", ada_name
);
309 add_verbose ("task body", ada_name
);
311 if (verbose_info
== 1)
312 strcat (ada_name
, ")");
317 ada_demangle (const char *coded_name
)
321 __gnat_decode (coded_name
, ada_name
, 0);
322 return xstrdup (ada_name
);