OSDN Git Service

PR middle-end/42068
[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
33 #if defined(IN_RTS)
34 #include "tconfig.h"
35 #include "tsystem.h"
36 #elif defined(IN_GCC)
37 #include "config.h"
38 #include "system.h"
39 #endif
40
41 #include <string.h>
42 #include <stdio.h>
43 #include <ctype.h>
44
45 #include "adaint.h"
46
47 #ifndef ISDIGIT
48 #define ISDIGIT(c) isdigit(c)
49 #endif
50
51 #ifndef PARMS
52 #define PARMS(ARGS) ARGS
53 #endif
54
55 #include "adadecode.h"
56
57 static void add_verbose (const char *, char *);
58 static int has_prefix (const char *, const char *);
59 static int has_suffix (const char *, const char *);
60
61 /* This is a safe version of strcpy that can be used with overlapped
62    pointers. Does nothing if s2 <= s1.  */
63 static void ostrcpy (char *s1, char *s2);
64
65 /* Set to nonzero if we have written any verbose info.  */
66 static int verbose_info;
67
68 /* Add TEXT to end of ADA_NAME, putting a leading " (" or ", ", depending
69    on VERBOSE_INFO.  */
70
71 static void add_verbose (const char *text, char *ada_name)
72 {
73   strcat (ada_name, verbose_info ? ", " : " (");
74   strcat (ada_name, text);
75
76   verbose_info = 1;
77 }
78
79 /* Returns 1 if NAME starts with PREFIX.  */
80
81 static int
82 has_prefix (const char *name, const char *prefix)
83 {
84   return strncmp (name, prefix, strlen (prefix)) == 0;
85 }
86
87 /* Returns 1 if NAME ends with SUFFIX.  */
88
89 static int
90 has_suffix (const char *name, const char *suffix)
91 {
92   int nlen = strlen (name);
93   int slen = strlen (suffix);
94
95   return nlen > slen && strncmp (name + nlen - slen, suffix, slen) == 0;
96 }
97
98 /* Safe overlapped pointers version of strcpy.  */
99
100 static void
101 ostrcpy (char *s1, char *s2)
102 {
103   if (s2 > s1)
104     {
105       while (*s2) *s1++ = *s2++;
106       *s1 = '\0';
107     }
108 }
109
110 /* This function will return the Ada name from the encoded form.
111    The Ada coding is done in exp_dbug.ads and this is the inverse function.
112    see exp_dbug.ads for full encoding rules, a short description is added
113    below. Right now only objects and routines are handled. Ada types are
114    stripped of their encodings.
115
116    CODED_NAME is the encoded entity name.
117
118    ADA_NAME is a pointer to a buffer, it will receive the Ada name. A safe
119    size for this buffer is: strlen (coded_name) * 2 + 60. (60 is for the
120    verbose information).
121
122    VERBOSE is nonzero if more information about the entity is to be
123    added at the end of the Ada name and surrounded by ( and ).
124
125      Coded name           Ada name                verbose info
126   ---------------------------------------------------------------------
127   _ada_xyz                xyz                     library level
128   x__y__z                 x.y.z
129   x__yTKB                 x.y                     task body
130   x__yB                   x.y                     task body
131   x__yX                   x.y                     body nested
132   x__yXb                  x.y                     body nested
133   xTK__y                  x.y                     in task
134   x__y$2                  x.y                     overloaded
135   x__y__3                 x.y                     overloaded
136   x__Oabs                 "abs"
137   x__Oand                 "and"
138   x__Omod                 "mod"
139   x__Onot                 "not"
140   x__Oor                  "or"
141   x__Orem                 "rem"
142   x__Oxor                 "xor"
143   x__Oeq                  "="
144   x__One                  "/="
145   x__Olt                  "<"
146   x__Ole                  "<="
147   x__Ogt                  ">"
148   x__Oge                  ">="
149   x__Oadd                 "+"
150   x__Osubtract            "-"
151   x__Oconcat              "&"
152   x__Omultiply            "*"
153   x__Odivide              "/"
154   x__Oexpon               "**"     */
155
156 void
157 __gnat_decode (const char *coded_name, char *ada_name, int verbose)
158 {
159   int lib_subprog = 0;
160   int overloaded = 0;
161   int task_body = 0;
162   int in_task = 0;
163   int body_nested = 0;
164
165   /* Check for library level subprogram.  */
166   if (has_prefix (coded_name, "_ada_"))
167     {
168       strcpy (ada_name, coded_name + 5);
169       lib_subprog = 1;
170     }
171   else
172     strcpy (ada_name, coded_name);
173
174   /* Check for the first triple underscore in the name. This indicates
175      that the name represents a type with encodings; in this case, we
176      need to strip the encodings.  */
177   {
178     char *encodings;
179
180     if ((encodings = (char *) strstr (ada_name, "___")) != NULL)
181       {
182         *encodings = '\0';
183       }
184   }
185
186   /* Check for task body.  */
187   if (has_suffix (ada_name, "TKB"))
188     {
189       ada_name[strlen (ada_name) - 3] = '\0';
190       task_body = 1;
191     }
192
193   if (has_suffix (ada_name, "B"))
194     {
195       ada_name[strlen (ada_name) - 1] = '\0';
196       task_body = 1;
197     }
198
199   /* Check for body-nested entity: X[bn] */
200   if (has_suffix (ada_name, "X"))
201     {
202       ada_name[strlen (ada_name) - 1] = '\0';
203       body_nested = 1;
204     }
205
206   if (has_suffix (ada_name, "Xb"))
207     {
208       ada_name[strlen (ada_name) - 2] = '\0';
209       body_nested = 1;
210     }
211
212   if (has_suffix (ada_name, "Xn"))
213     {
214       ada_name[strlen (ada_name) - 2] = '\0';
215       body_nested = 1;
216     }
217
218   /* Change instance of TK__ (object declared inside a task) to __.  */
219   {
220     char *tktoken;
221
222     while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
223       {
224         ostrcpy (tktoken, tktoken + 2);
225         in_task = 1;
226       }
227   }
228
229   /* Check for overloading: name terminated by $nn or __nn.  */
230   {
231     int len = strlen (ada_name);
232     int n_digits = 0;
233
234     if (len > 1)
235       while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
236         n_digits++;
237
238     /* Check if we have $ or __ before digits.  */
239     if (ada_name[len - 1 - n_digits] == '$')
240       {
241         ada_name[len - 1 - n_digits] = '\0';
242         overloaded = 1;
243       }
244     else if (ada_name[len - 1 - n_digits] == '_'
245              && ada_name[len - 1 - n_digits - 1] == '_')
246       {
247         ada_name[len - 1 - n_digits - 1] = '\0';
248         overloaded = 1;
249       }
250   }
251
252   /* Check for nested subprogram ending in .nnnn and strip suffix. */
253   {
254     int last = strlen (ada_name) - 1;
255
256     while (ISDIGIT (ada_name[last]) && last > 0)
257       {
258         last--;
259       }
260
261     if (ada_name[last] == '.')
262       {
263         ada_name[last] = (char) 0;
264       }
265   }
266
267   /* Change all "__" to ".". */
268   {
269     int len = strlen (ada_name);
270     int k = 0;
271
272     while (k < len)
273       {
274         if (ada_name[k] == '_' && ada_name[k+1] == '_')
275           {
276             ada_name[k] = '.';
277             ostrcpy (ada_name + k + 1, ada_name + k + 2);
278             len = len - 1;
279           }
280         k++;
281       }
282   }
283
284   /* Checks for operator name.  */
285   {
286     const char *trans_table[][2]
287       = {{"Oabs", "\"abs\""},  {"Oand", "\"and\""},    {"Omod", "\"mod\""},
288          {"Onot", "\"not\""},  {"Oor", "\"or\""},      {"Orem", "\"rem\""},
289          {"Oxor", "\"xor\""},  {"Oeq", "\"=\""},       {"One", "\"/=\""},
290          {"Olt", "\"<\""},     {"Ole", "\"<=\""},      {"Ogt", "\">\""},
291          {"Oge", "\">=\""},    {"Oadd", "\"+\""},      {"Osubtract", "\"-\""},
292          {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
293          {"Oexpon", "\"**\""}, {NULL, NULL} };
294     int k = 0;
295
296     while (1)
297       {
298         char *optoken;
299
300         if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
301           {
302             int codedlen = strlen (trans_table[k][0]);
303             int oplen = strlen (trans_table[k][1]);
304
305             if (codedlen > oplen)
306               /* We shrink the space.  */
307               ostrcpy (optoken, optoken + codedlen - oplen);
308             else if (oplen > codedlen)
309               {
310                 /* We need more space.  */
311                 int len = strlen (ada_name);
312                 int space = oplen - codedlen;
313                 int num_to_move = &ada_name[len] - optoken;
314                 int t;
315
316                 for (t = 0; t < num_to_move; t++)
317                   ada_name[len + space - t - 1] = ada_name[len - t - 1];
318               }
319
320             /* Write symbol in the space.  */
321             strncpy (optoken, trans_table[k][1], oplen);
322           }
323         else
324           k++;
325
326         /* Check for table's ending.  */
327         if (trans_table[k][0] == NULL)
328           break;
329       }
330   }
331
332   /* If verbose mode is on, we add some information to the Ada name.  */
333   if (verbose)
334     {
335       if (overloaded)
336         add_verbose ("overloaded", ada_name);
337
338       if (lib_subprog)
339         add_verbose ("library level", ada_name);
340
341       if (body_nested)
342         add_verbose ("body nested", ada_name);
343
344       if (in_task)
345         add_verbose ("in task", ada_name);
346
347       if (task_body)
348         add_verbose ("task body", ada_name);
349
350       if (verbose_info == 1)
351         strcat (ada_name, ")");
352     }
353 }
354
355 #ifdef IN_GCC
356 char *
357 ada_demangle (const char *coded_name)
358 {
359   char ada_name[2048];
360
361   __gnat_decode (coded_name, ada_name, 0);
362   return xstrdup (ada_name);
363 }
364 #endif
365
366 void
367 get_encoding (const char *coded_name, char *encoding)
368 {
369   char * dest_index = encoding;
370   const char *p;
371   int found = 0;
372   int count = 0;
373
374   /* The heuristics is the following: we assume that the first triple
375      underscore in an encoded name indicates the beginning of the
376      first encoding, and that subsequent triple underscores indicate
377      the next encodings. We assume that the encodings are always at the
378      end of encoded names.  */
379
380   for (p = coded_name; *p != '\0'; p++)
381     {
382       if (*p != '_')
383         count = 0;
384       else
385         if (++count == 3)
386           {
387             count = 0;
388
389             if (found)
390               {
391                 dest_index = dest_index - 2;
392                 *dest_index++ = ':';
393               }
394
395             p++;
396             found = 1;
397           }
398
399       if (found)
400         *dest_index++ = *p;
401     }
402
403   *dest_index = '\0';
404 }