OSDN Git Service

Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[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-2009, 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 3,  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.                                     *
17  *                                                                          *
18  * As a special exception under Section 7 of GPL version 3, you are granted *
19  * additional permissions described in the GCC Runtime Library Exception,   *
20  * version 3.1, as published by the Free Software Foundation.               *
21  *                                                                          *
22  * You should have received a copy of the GNU General Public License and    *
23  * a copy of the GCC Runtime Library Exception along with this program;     *
24  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
25  * <http://www.gnu.org/licenses/>.                                          *
26  *                                                                          *
27  * GNAT was originally developed  by the GNAT team at  New York University. *
28  * Extensive contributions were provided by Ada Core Technologies Inc.      *
29  *                                                                          *
30  ****************************************************************************/
31
32 #ifdef IN_GCC
33 #include "config.h"
34 #include "system.h"
35 #else
36 #include <stdio.h>
37 #include <ctype.h>
38 #define ISDIGIT(c) isdigit(c)
39 #define PARMS(ARGS) ARGS
40 #endif
41
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. Ada types are
101    stripped of their encodings.
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 the first triple underscore in the name. This indicates
162      that the name represents a type with encodings; in this case, we
163      need to strip the encodings.  */
164   {
165     char *encodings;
166
167     if ((encodings = (char *) strstr (ada_name, "___")) != NULL)
168       {
169         *encodings = '\0';
170       }
171   }
172
173   /* Check for task body.  */
174   if (has_suffix (ada_name, "TKB"))
175     {
176       ada_name[strlen (ada_name) - 3] = '\0';
177       task_body = 1;
178     }
179
180   if (has_suffix (ada_name, "B"))
181     {
182       ada_name[strlen (ada_name) - 1] = '\0';
183       task_body = 1;
184     }
185
186   /* Check for body-nested entity: X[bn] */
187   if (has_suffix (ada_name, "X"))
188     {
189       ada_name[strlen (ada_name) - 1] = '\0';
190       body_nested = 1;
191     }
192
193   if (has_suffix (ada_name, "Xb"))
194     {
195       ada_name[strlen (ada_name) - 2] = '\0';
196       body_nested = 1;
197     }
198
199   if (has_suffix (ada_name, "Xn"))
200     {
201       ada_name[strlen (ada_name) - 2] = '\0';
202       body_nested = 1;
203     }
204
205   /* Change instance of TK__ (object declared inside a task) to __.  */
206   {
207     char *tktoken;
208
209     while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
210       {
211         ostrcpy (tktoken, tktoken + 2);
212         in_task = 1;
213       }
214   }
215
216   /* Check for overloading: name terminated by $nn or __nn.  */
217   {
218     int len = strlen (ada_name);
219     int n_digits = 0;
220
221     if (len > 1)
222       while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
223         n_digits++;
224
225     /* Check if we have $ or __ before digits.  */
226     if (ada_name[len - 1 - n_digits] == '$')
227       {
228         ada_name[len - 1 - n_digits] = '\0';
229         overloaded = 1;
230       }
231     else if (ada_name[len - 1 - n_digits] == '_'
232              && ada_name[len - 1 - n_digits - 1] == '_')
233       {
234         ada_name[len - 1 - n_digits - 1] = '\0';
235         overloaded = 1;
236       }
237   }
238
239   /* Change all "__" to ".". */
240   {
241     int len = strlen (ada_name);
242     int k = 0;
243
244     while (k < len)
245       {
246         if (ada_name[k] == '_' && ada_name[k+1] == '_')
247           {
248             ada_name[k] = '.';
249             ostrcpy (ada_name + k + 1, ada_name + k + 2);
250             len = len - 1;
251           }
252         k++;
253       }
254   }
255
256   /* Checks for operator name.  */
257   {
258     const char *trans_table[][2]
259       = {{"Oabs", "\"abs\""},  {"Oand", "\"and\""},    {"Omod", "\"mod\""},
260          {"Onot", "\"not\""},  {"Oor", "\"or\""},      {"Orem", "\"rem\""},
261          {"Oxor", "\"xor\""},  {"Oeq", "\"=\""},       {"One", "\"/=\""},
262          {"Olt", "\"<\""},     {"Ole", "\"<=\""},      {"Ogt", "\">\""},
263          {"Oge", "\">=\""},    {"Oadd", "\"+\""},      {"Osubtract", "\"-\""},
264          {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
265          {"Oexpon", "\"**\""}, {NULL, NULL} };
266     int k = 0;
267
268     while (1)
269       {
270         char *optoken;
271
272         if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
273           {
274             int codedlen = strlen (trans_table[k][0]);
275             int oplen = strlen (trans_table[k][1]);
276
277             if (codedlen > oplen)
278               /* We shrink the space.  */
279               ostrcpy (optoken, optoken + codedlen - oplen);
280             else if (oplen > codedlen)
281               {
282                 /* We need more space.  */
283                 int len = strlen (ada_name);
284                 int space = oplen - codedlen;
285                 int num_to_move = &ada_name[len] - optoken;
286                 int t;
287
288                 for (t = 0; t < num_to_move; t++)
289                   ada_name[len + space - t - 1] = ada_name[len - t - 1];
290               }
291
292             /* Write symbol in the space.  */
293             strncpy (optoken, trans_table[k][1], oplen);
294           }
295         else
296           k++;
297
298         /* Check for table's ending.  */
299         if (trans_table[k][0] == NULL)
300           break;
301       }
302   }
303
304   /* If verbose mode is on, we add some information to the Ada name.  */
305   if (verbose)
306     {
307       if (overloaded)
308         add_verbose ("overloaded", ada_name);
309
310       if (lib_subprog)
311         add_verbose ("library level", ada_name);
312
313       if (body_nested)
314         add_verbose ("body nested", ada_name);
315
316       if (in_task)
317         add_verbose ("in task", ada_name);
318
319       if (task_body)
320         add_verbose ("task body", ada_name);
321
322       if (verbose_info == 1)
323         strcat (ada_name, ")");
324     }
325 }
326
327 char *
328 ada_demangle (const char *coded_name)
329 {
330   char ada_name[2048];
331
332   __gnat_decode (coded_name, ada_name, 0);
333   return xstrdup (ada_name);
334 }
335
336 void
337 get_encoding (const char *coded_name, char *encoding)
338 {
339   char * dest_index = encoding;
340   const char *p;
341   int found = 0;
342   int count = 0;
343
344   /* The heuristics is the following: we assume that the first triple
345      underscore in an encoded name indicates the beginning of the
346      first encoding, and that subsequent triple underscores indicate
347      the next encodings. We assume that the encodings are always at the
348      end of encoded names.  */
349
350   for (p = coded_name; *p != '\0'; p++)
351     {
352       if (*p != '_')
353         count = 0;
354       else
355         if (++count == 3)
356           {
357             count = 0;
358
359             if (found)
360               {
361                 dest_index = dest_index - 2;
362                 *dest_index++ = ':';
363               }
364
365             p++;
366             found = 1;
367           }
368
369       if (found)
370         *dest_index++ = *p;
371     }
372
373   *dest_index = '\0';
374 }