OSDN Git Service

Add Fariborz to my last change.
[pf3gnuchains/gcc-fork.git] / gcc / ada / adadecode.c
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-2003, 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,  59 Temple Place - Suite 330,  Boston, *
20  * MA 02111-1307, 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  ****************************************************************************/
32
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
42
43 #include "adadecode.h"
44
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 *);
48
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);
52
53 /* Set to nonzero if we have written any verbose info.  */
54 static int verbose_info;
55
56 /* Add TEXT to end of ADA_NAME, putting a leading " (" or ", ", depending
57    on VERBOSE_INFO.  */
58
59 static void add_verbose (const char *text, char *ada_name)
60 {
61   strcat (ada_name, verbose_info ? ", " : " (");
62   strcat (ada_name, text);
63
64   verbose_info = 1;
65 }
66
67 /* Returns 1 if NAME starts with PREFIX.  */
68
69 static int
70 has_prefix (const char *name, const char *prefix)
71 {
72   return strncmp (name, prefix, strlen (prefix)) == 0;
73 }
74
75 /* Returns 1 if NAME ends with SUFFIX.  */
76
77 static int
78 has_suffix (const char *name, const char *suffix)
79 {
80   int nlen = strlen (name);
81   int slen = strlen (suffix);
82
83   return nlen > slen && strncmp (name + nlen - slen, suffix, slen) == 0;
84 }
85
86 /* Safe overlapped pointers version of strcpy.  */
87
88 static void
89 ostrcpy (char *s1, char *s2)
90 {
91   if (s2 > s1)
92     {
93       while (*s2) *s1++ = *s2++;
94       *s1 = '\0';
95     }
96 }
97
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
102    for Ada types.
103
104    CODED_NAME is the encoded entity name.
105
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).
109
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 ).
112
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               "**"     */
143
144 void
145 __gnat_decode (const char *coded_name, char *ada_name, int verbose)
146 {
147   int lib_subprog = 0;
148   int overloaded = 0;
149   int task_body = 0;
150   int in_task = 0;
151   int body_nested = 0;
152
153   /* Check for library level subprogram.  */
154   if (has_prefix (coded_name, "_ada_"))
155     {
156       strcpy (ada_name, coded_name + 5);
157       lib_subprog = 1;
158     }
159   else
160     strcpy (ada_name, coded_name);
161
162   /* Check for task body.  */
163   if (has_suffix (ada_name, "TKB"))
164     {
165       ada_name[strlen (ada_name) - 3] = '\0';
166       task_body = 1;
167     }
168
169   if (has_suffix (ada_name, "B"))
170     {
171       ada_name[strlen (ada_name) - 1] = '\0';
172       task_body = 1;
173     }
174
175   /* Check for body-nested entity: X[bn] */
176   if (has_suffix (ada_name, "X"))
177     {
178       ada_name[strlen (ada_name) - 1] = '\0';
179       body_nested = 1;
180     }
181
182   if (has_suffix (ada_name, "Xb"))
183     {
184       ada_name[strlen (ada_name) - 2] = '\0';
185       body_nested = 1;
186     }
187
188   if (has_suffix (ada_name, "Xn"))
189     {
190       ada_name[strlen (ada_name) - 2] = '\0';
191       body_nested = 1;
192     }
193
194   /* Change instance of TK__ (object declared inside a task) to __.  */
195   {
196     char *tktoken;
197
198     while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
199       {
200         ostrcpy (tktoken, tktoken + 2);
201         in_task = 1;
202       }
203   }
204
205   /* Check for overloading: name terminated by $nn or __nn.  */
206   {
207     int len = strlen (ada_name);
208     int n_digits = 0;
209
210     if (len > 1)
211       while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
212         n_digits++;
213
214     /* Check if we have $ or __ before digits.  */
215     if (ada_name[len - 1 - n_digits] == '$')
216       {
217         ada_name[len - 1 - n_digits] = '\0';
218         overloaded = 1;
219       }
220     else if (ada_name[len - 1 - n_digits] == '_'
221              && ada_name[len - 1 - n_digits - 1] == '_')
222       {
223         ada_name[len - 1 - n_digits - 1] = '\0';
224         overloaded = 1;
225       }
226   }
227
228   /* Change all "__" to ".". */
229   {
230     int len = strlen (ada_name);
231     int k = 0;
232
233     while (k < len)
234       {
235         if (ada_name[k] == '_' && ada_name[k+1] == '_')
236           {
237             ada_name[k] = '.';
238             ostrcpy (ada_name + k + 1, ada_name + k + 2);
239             len = len - 1;
240           }
241         k++;
242       }
243   }
244
245   /* Checks for operator name.  */
246   {
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} };
255     int k = 0;
256
257     while (1)
258       {
259         char *optoken;
260
261         if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
262           {
263             int codedlen = strlen (trans_table[k][0]);
264             int oplen = strlen (trans_table[k][1]);
265
266             if (codedlen > oplen)
267               /* We shrink the space.  */
268               ostrcpy (optoken, optoken + codedlen - oplen);
269             else if (oplen > codedlen)
270               {
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;
275                 int t;
276
277                 for (t = 0; t < num_to_move; t++)
278                   ada_name[len + space - t - 1] = ada_name[len - t - 1];
279               }
280
281             /* Write symbol in the space.  */
282             strncpy (optoken, trans_table[k][1], oplen);
283           }
284         else
285           k++;
286
287         /* Check for table's ending.  */
288         if (trans_table[k][0] == NULL)
289           break;
290       }
291   }
292
293   /* If verbose mode is on, we add some information to the Ada name.  */
294   if (verbose)
295     {
296       if (overloaded)
297         add_verbose ("overloaded", ada_name);
298
299       if (lib_subprog)
300         add_verbose ("library level", ada_name);
301
302       if (body_nested)
303         add_verbose ("body nested", ada_name);
304
305       if (in_task)
306         add_verbose ("in task", ada_name);
307
308       if (task_body)
309         add_verbose ("task body", ada_name);
310
311       if (verbose_info == 1)
312         strcat (ada_name, ")");
313     }
314 }
315
316 char *
317 ada_demangle (const char *coded_name)
318 {
319   char ada_name[2048];
320
321   __gnat_decode (coded_name, ada_name, 0);
322   return xstrdup (ada_name);
323 }