OSDN Git Service

2009-07-27 Emmanuel Briot <briot@adacore.com>
[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 <string.h>
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. Ada types are
102    stripped of their encodings.
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 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.  */
165   {
166     char *encodings;
167
168     if ((encodings = (char *) strstr (ada_name, "___")) != NULL)
169       {
170         *encodings = '\0';
171       }
172   }
173
174   /* Check for task body.  */
175   if (has_suffix (ada_name, "TKB"))
176     {
177       ada_name[strlen (ada_name) - 3] = '\0';
178       task_body = 1;
179     }
180
181   if (has_suffix (ada_name, "B"))
182     {
183       ada_name[strlen (ada_name) - 1] = '\0';
184       task_body = 1;
185     }
186
187   /* Check for body-nested entity: X[bn] */
188   if (has_suffix (ada_name, "X"))
189     {
190       ada_name[strlen (ada_name) - 1] = '\0';
191       body_nested = 1;
192     }
193
194   if (has_suffix (ada_name, "Xb"))
195     {
196       ada_name[strlen (ada_name) - 2] = '\0';
197       body_nested = 1;
198     }
199
200   if (has_suffix (ada_name, "Xn"))
201     {
202       ada_name[strlen (ada_name) - 2] = '\0';
203       body_nested = 1;
204     }
205
206   /* Change instance of TK__ (object declared inside a task) to __.  */
207   {
208     char *tktoken;
209
210     while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
211       {
212         ostrcpy (tktoken, tktoken + 2);
213         in_task = 1;
214       }
215   }
216
217   /* Check for overloading: name terminated by $nn or __nn.  */
218   {
219     int len = strlen (ada_name);
220     int n_digits = 0;
221
222     if (len > 1)
223       while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
224         n_digits++;
225
226     /* Check if we have $ or __ before digits.  */
227     if (ada_name[len - 1 - n_digits] == '$')
228       {
229         ada_name[len - 1 - n_digits] = '\0';
230         overloaded = 1;
231       }
232     else if (ada_name[len - 1 - n_digits] == '_'
233              && ada_name[len - 1 - n_digits - 1] == '_')
234       {
235         ada_name[len - 1 - n_digits - 1] = '\0';
236         overloaded = 1;
237       }
238   }
239
240   /* Change all "__" to ".". */
241   {
242     int len = strlen (ada_name);
243     int k = 0;
244
245     while (k < len)
246       {
247         if (ada_name[k] == '_' && ada_name[k+1] == '_')
248           {
249             ada_name[k] = '.';
250             ostrcpy (ada_name + k + 1, ada_name + k + 2);
251             len = len - 1;
252           }
253         k++;
254       }
255   }
256
257   /* Checks for operator name.  */
258   {
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;
268
269     while (1)
270       {
271         char *optoken;
272
273         if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
274           {
275             int codedlen = strlen (trans_table[k][0]);
276             int oplen = strlen (trans_table[k][1]);
277
278             if (codedlen > oplen)
279               /* We shrink the space.  */
280               ostrcpy (optoken, optoken + codedlen - oplen);
281             else if (oplen > codedlen)
282               {
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;
288
289                 for (t = 0; t < num_to_move; t++)
290                   ada_name[len + space - t - 1] = ada_name[len - t - 1];
291               }
292
293             /* Write symbol in the space.  */
294             strncpy (optoken, trans_table[k][1], oplen);
295           }
296         else
297           k++;
298
299         /* Check for table's ending.  */
300         if (trans_table[k][0] == NULL)
301           break;
302       }
303   }
304
305   /* If verbose mode is on, we add some information to the Ada name.  */
306   if (verbose)
307     {
308       if (overloaded)
309         add_verbose ("overloaded", ada_name);
310
311       if (lib_subprog)
312         add_verbose ("library level", ada_name);
313
314       if (body_nested)
315         add_verbose ("body nested", ada_name);
316
317       if (in_task)
318         add_verbose ("in task", ada_name);
319
320       if (task_body)
321         add_verbose ("task body", ada_name);
322
323       if (verbose_info == 1)
324         strcat (ada_name, ")");
325     }
326 }
327
328 #ifdef IN_GCC
329 char *
330 ada_demangle (const char *coded_name)
331 {
332   char ada_name[2048];
333
334   __gnat_decode (coded_name, ada_name, 0);
335   return xstrdup (ada_name);
336 }
337 #endif
338
339 void
340 get_encoding (const char *coded_name, char *encoding)
341 {
342   char * dest_index = encoding;
343   const char *p;
344   int found = 0;
345   int count = 0;
346
347   /* The heuristics is the following: we assume that the first triple
348      underscore in an encoded name indicates the beginning of the
349      first encoding, and that subsequent triple underscores indicate
350      the next encodings. We assume that the encodings are always at the
351      end of encoded names.  */
352
353   for (p = coded_name; *p != '\0'; p++)
354     {
355       if (*p != '_')
356         count = 0;
357       else
358         if (++count == 3)
359           {
360             count = 0;
361
362             if (found)
363               {
364                 dest_index = dest_index - 2;
365                 *dest_index++ = ':';
366               }
367
368             p++;
369             found = 1;
370           }
371
372       if (found)
373         *dest_index++ = *p;
374     }
375
376   *dest_index = '\0';
377 }