Merge from mainline
[official-gcc.git] / gcc / ada / adadecode.c
blob12fcd02c702c84dbffb67f1ed2bee2b778052e42
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * A D A D E C O D E *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2001-2006, Free Software Foundation, Inc. *
10 * *
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, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
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. *
27 * *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 * *
31 ****************************************************************************/
33 #ifdef IN_GCC
34 #include "config.h"
35 #include "system.h"
36 #else
37 #include <stdio.h>
38 #include <ctype.h>
39 #define ISDIGIT(c) isdigit(c)
40 #define PARMS(ARGS) ARGS
41 #endif
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
57 on VERBOSE_INFO. */
59 static void add_verbose (const char *text, char *ada_name)
61 strcat (ada_name, verbose_info ? ", " : " (");
62 strcat (ada_name, text);
64 verbose_info = 1;
67 /* Returns 1 if NAME starts with PREFIX. */
69 static int
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. */
77 static int
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. */
88 static void
89 ostrcpy (char *s1, char *s2)
91 if (s2 > s1)
93 while (*s2) *s1++ = *s2++;
94 *s1 = '\0';
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
116 x__y__z x.y.z
117 x__yTKB x.y task body
118 x__yB x.y task body
119 x__yX x.y body nested
120 x__yXb x.y body nested
121 xTK__y x.y in task
122 x__y$2 x.y overloaded
123 x__y__3 x.y overloaded
124 x__Oabs "abs"
125 x__Oand "and"
126 x__Omod "mod"
127 x__Onot "not"
128 x__Oor "or"
129 x__Orem "rem"
130 x__Oxor "xor"
131 x__Oeq "="
132 x__One "/="
133 x__Olt "<"
134 x__Ole "<="
135 x__Ogt ">"
136 x__Oge ">="
137 x__Oadd "+"
138 x__Osubtract "-"
139 x__Oconcat "&"
140 x__Omultiply "*"
141 x__Odivide "/"
142 x__Oexpon "**" */
144 void
145 __gnat_decode (const char *coded_name, char *ada_name, int verbose)
147 int lib_subprog = 0;
148 int overloaded = 0;
149 int task_body = 0;
150 int in_task = 0;
151 int body_nested = 0;
153 /* Check for library level subprogram. */
154 if (has_prefix (coded_name, "_ada_"))
156 strcpy (ada_name, coded_name + 5);
157 lib_subprog = 1;
159 else
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. */
166 char *encodings;
168 if ((encodings = (char *) strstr (ada_name, "___")) != NULL)
170 *encodings = '\0';
174 /* Check for task body. */
175 if (has_suffix (ada_name, "TKB"))
177 ada_name[strlen (ada_name) - 3] = '\0';
178 task_body = 1;
181 if (has_suffix (ada_name, "B"))
183 ada_name[strlen (ada_name) - 1] = '\0';
184 task_body = 1;
187 /* Check for body-nested entity: X[bn] */
188 if (has_suffix (ada_name, "X"))
190 ada_name[strlen (ada_name) - 1] = '\0';
191 body_nested = 1;
194 if (has_suffix (ada_name, "Xb"))
196 ada_name[strlen (ada_name) - 2] = '\0';
197 body_nested = 1;
200 if (has_suffix (ada_name, "Xn"))
202 ada_name[strlen (ada_name) - 2] = '\0';
203 body_nested = 1;
206 /* Change instance of TK__ (object declared inside a task) to __. */
208 char *tktoken;
210 while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
212 ostrcpy (tktoken, tktoken + 2);
213 in_task = 1;
217 /* Check for overloading: name terminated by $nn or __nn. */
219 int len = strlen (ada_name);
220 int n_digits = 0;
222 if (len > 1)
223 while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
224 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';
230 overloaded = 1;
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';
236 overloaded = 1;
240 /* Change all "__" to ".". */
242 int len = strlen (ada_name);
243 int k = 0;
245 while (k < len)
247 if (ada_name[k] == '_' && ada_name[k+1] == '_')
249 ada_name[k] = '.';
250 ostrcpy (ada_name + k + 1, ada_name + k + 2);
251 len = len - 1;
253 k++;
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} };
267 int k = 0;
269 while (1)
271 char *optoken;
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;
287 int t;
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);
296 else
297 k++;
299 /* Check for table's ending. */
300 if (trans_table[k][0] == NULL)
301 break;
305 /* If verbose mode is on, we add some information to the Ada name. */
306 if (verbose)
308 if (overloaded)
309 add_verbose ("overloaded", ada_name);
311 if (lib_subprog)
312 add_verbose ("library level", ada_name);
314 if (body_nested)
315 add_verbose ("body nested", ada_name);
317 if (in_task)
318 add_verbose ("in task", ada_name);
320 if (task_body)
321 add_verbose ("task body", ada_name);
323 if (verbose_info == 1)
324 strcat (ada_name, ")");
328 char *
329 ada_demangle (const char *coded_name)
331 char ada_name[2048];
333 __gnat_decode (coded_name, ada_name, 0);
334 return xstrdup (ada_name);
337 void
338 get_encoding (const char *coded_name, char *encoding)
340 char * dest_index = encoding;
341 const char *p;
342 int found = 0;
343 int count = 0;
345 /* The heuristics is the following: we assume that the first triple
346 underscore in an encoded name indicates the beginning of the
347 first encoding, and that subsequent triple underscores indicate
348 the next encodings. We assume that the encodings are always at the
349 end of encoded names. */
351 for (p = coded_name; *p != '\0'; p++)
353 if (*p != '_')
354 count = 0;
355 else
356 if (++count == 3)
358 count = 0;
360 if (found)
362 dest_index = dest_index - 2;
363 *dest_index++ = ':';
366 p++;
367 found = 1;
370 if (found)
371 *dest_index++ = *p;
374 *dest_index = '\0';