OSDN Git Service

* sysdep.c: Problem discovered during IA64 VMS port.
[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 #define PARMS(ARGS) ARGS
39 #endif
40
41 #include "ctype.h"
42 #include "adadecode.h"
43
44 static void add_verbose (const char *, char *);
45 static int has_prefix (const char *, const char *);
46 static int has_suffix (const char *, const char *);
47
48 /* This is a safe version of strcpy that can be used with overlapped
49    pointers. Does nothing if s2 <= s1.  */
50 static void ostrcpy (char *s1, char *s2);
51
52 /* Set to nonzero if we have written any verbose info.  */
53 static int verbose_info;
54
55 /* Add TEXT to end of ADA_NAME, putting a leading " (" or ", ", depending
56    on VERBOSE_INFO.  */
57
58 static void add_verbose (const char *text, char *ada_name)
59 {
60   strcat (ada_name, verbose_info ? ", " : " (");
61   strcat (ada_name, text);
62
63   verbose_info = 1;
64 }
65
66 /* Returns 1 if NAME starts with PREFIX.  */
67
68 static int
69 has_prefix (const char *name, const char *prefix)
70 {
71   return strncmp (name, prefix, strlen (prefix)) == 0;
72 }
73
74 /* Returns 1 if NAME ends with SUFFIX.  */
75
76 static int
77 has_suffix (const char *name, const char *suffix)
78 {
79   int nlen = strlen (name);
80   int slen = strlen (suffix);
81
82   return nlen > slen && strncmp (name + nlen - slen, suffix, slen) == 0;
83 }
84
85 /* Safe overlapped pointers version of strcpy.  */
86
87 static void
88 ostrcpy (char *s1, char *s2)
89 {
90   if (s2 > s1)
91     {
92       while (*s2) *s1++ = *s2++;
93       *s1 = '\0';
94     }
95 }
96
97 /* This function will return the Ada name from the encoded form.
98    The Ada coding is done in exp_dbug.ads and this is the inverse function.
99    see exp_dbug.ads for full encoding rules, a short description is added
100    below. Right now only objects and routines are handled. There is no support
101    for Ada types.
102
103    CODED_NAME is the encoded entity name.
104
105    ADA_NAME is a pointer to a buffer, it will receive the Ada name. A safe
106    size for this buffer is: strlen (coded_name) * 2 + 60. (60 is for the
107    verbose information).
108
109    VERBOSE is nonzero if more information about the entity is to be
110    added at the end of the Ada name and surrounded by ( and ).
111
112      Coded name           Ada name                verbose info
113   ---------------------------------------------------------------------
114   _ada_xyz                xyz                     library level
115   x__y__z                 x.y.z
116   x__yTKB                 x.y                     task body
117   x__yB                   x.y                     task body
118   x__yX                   x.y                     body nested
119   x__yXb                  x.y                     body nested
120   xTK__y                  x.y                     in task
121   x__y$2                  x.y                     overloaded
122   x__y__3                 x.y                     overloaded
123   x__Oabs                 "abs"
124   x__Oand                 "and"
125   x__Omod                 "mod"
126   x__Onot                 "not"
127   x__Oor                  "or"
128   x__Orem                 "rem"
129   x__Oxor                 "xor"
130   x__Oeq                  "="
131   x__One                  "/="
132   x__Olt                  "<"
133   x__Ole                  "<="
134   x__Ogt                  ">"
135   x__Oge                  ">="
136   x__Oadd                 "+"
137   x__Osubtract            "-"
138   x__Oconcat              "&"
139   x__Omultiply            "*"
140   x__Odivide              "/"
141   x__Oexpon               "**"     */
142
143 void
144 __gnat_decode (const char *coded_name, char *ada_name, int verbose)
145 {
146   int lib_subprog = 0;
147   int overloaded = 0;
148   int task_body = 0;
149   int in_task = 0;
150   int body_nested = 0;
151
152   /* Check for library level subprogram.  */
153   if (has_prefix (coded_name, "_ada_"))
154     {
155       strcpy (ada_name, coded_name + 5);
156       lib_subprog = 1;
157     }
158   else
159     strcpy (ada_name, coded_name);
160
161   /* Check for task body.  */
162   if (has_suffix (ada_name, "TKB"))
163     {
164       ada_name[strlen (ada_name) - 3] = '\0';
165       task_body = 1;
166     }
167
168   if (has_suffix (ada_name, "B"))
169     {
170       ada_name[strlen (ada_name) - 1] = '\0';
171       task_body = 1;
172     }
173
174   /* Check for body-nested entity: X[bn] */
175   if (has_suffix (ada_name, "X"))
176     {
177       ada_name[strlen (ada_name) - 1] = '\0';
178       body_nested = 1;
179     }
180
181   if (has_suffix (ada_name, "Xb"))
182     {
183       ada_name[strlen (ada_name) - 2] = '\0';
184       body_nested = 1;
185     }
186
187   if (has_suffix (ada_name, "Xn"))
188     {
189       ada_name[strlen (ada_name) - 2] = '\0';
190       body_nested = 1;
191     }
192
193   /* Change instance of TK__ (object declared inside a task) to __.  */
194   {
195     char *tktoken;
196
197     while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
198       {
199         ostrcpy (tktoken, tktoken + 2);
200         in_task = 1;
201       }
202   }
203
204   /* Check for overloading: name terminated by $nn or __nn.  */
205   {
206     int len = strlen (ada_name);
207     int n_digits = 0;
208
209     if (len > 1)
210       while (isdigit ((int) ada_name[(int) len - 1 - n_digits]))
211         n_digits++;
212
213     /* Check if we have $ or __ before digits.  */
214     if (ada_name[len - 1 - n_digits] == '$')
215       {
216         ada_name[len - 1 - n_digits] = '\0';
217         overloaded = 1;
218       }
219     else if (ada_name[len - 1 - n_digits] == '_'
220              && ada_name[len - 1 - n_digits - 1] == '_')
221       {
222         ada_name[len - 1 - n_digits - 1] = '\0';
223         overloaded = 1;
224       }
225   }
226
227   /* Change all "__" to ".". */
228   {
229     int len = strlen (ada_name);
230     int k = 0;
231
232     while (k < len)
233       {
234         if (ada_name[k] == '_' && ada_name[k+1] == '_')
235           {
236             ada_name[k] = '.';
237             ostrcpy (ada_name + k + 1, ada_name + k + 2);
238             len = len - 1;
239           }
240         k++;
241       }
242   }
243
244   /* Checks for operator name.  */
245   {
246     const char *trans_table[][2]
247       = {{"Oabs", "\"abs\""},  {"Oand", "\"and\""},    {"Omod", "\"mod\""},
248          {"Onot", "\"not\""},  {"Oor", "\"or\""},      {"Orem", "\"rem\""},
249          {"Oxor", "\"xor\""},  {"Oeq", "\"=\""},       {"One", "\"/=\""},
250          {"Olt", "\"<\""},     {"Ole", "\"<=\""},      {"Ogt", "\">\""},
251          {"Oge", "\">=\""},    {"Oadd", "\"+\""},      {"Osubtract", "\"-\""},
252          {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
253          {"Oexpon", "\"**\""}, {NULL, NULL} };
254     int k = 0;
255
256     while (1)
257       {
258         char *optoken;
259
260         if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
261           {
262             int codedlen = strlen (trans_table[k][0]);
263             int oplen = strlen (trans_table[k][1]);
264
265             if (codedlen > oplen)
266               /* We shrink the space.  */
267               ostrcpy (optoken, optoken + codedlen - oplen);
268             else if (oplen > codedlen)
269               {
270                 /* We need more space.  */
271                 int len = strlen (ada_name);
272                 int space = oplen - codedlen;
273                 int num_to_move = &ada_name[len] - optoken;
274                 int t;
275
276                 for (t = 0; t < num_to_move; t++)
277                   ada_name[len + space - t - 1] = ada_name[len - t - 1];
278               }
279
280             /* Write symbol in the space.  */
281             strncpy (optoken, trans_table[k][1], oplen);
282           }
283         else
284           k++;
285
286         /* Check for table's ending.  */
287         if (trans_table[k][0] == NULL)
288           break;
289       }
290   }
291
292   /* If verbose mode is on, we add some information to the Ada name.  */
293   if (verbose)
294     {
295       if (overloaded)
296         add_verbose ("overloaded", ada_name);
297
298       if (lib_subprog)
299         add_verbose ("library level", ada_name);
300
301       if (body_nested)
302         add_verbose ("body nested", ada_name);
303
304       if (in_task)
305         add_verbose ("in task", ada_name);
306
307       if (task_body)
308         add_verbose ("task body", ada_name);
309
310       if (verbose_info == 1)
311         strcat (ada_name, ")");
312     }
313 }
314
315 char *
316 ada_demangle (const char *coded_name)
317 {
318   char ada_name[2048];
319
320   __gnat_decode (coded_name, ada_name, 0);
321   return xstrdup (ada_name);
322 }