gdb: GC old versions
[dragonfly.git] / contrib / gdb-7 / gdb / jv-typeprint.c
1 /* Support for printing Java types for GDB, the GNU debugger.
2    Copyright (C) 1997, 1998, 1999, 2000, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20
21 #include "defs.h"
22 #include "symtab.h"
23 #include "gdbtypes.h"
24 #include "value.h"
25 #include "demangle.h"
26 #include "jv-lang.h"
27 #include "gdb_string.h"
28 #include "typeprint.h"
29 #include "c-lang.h"
30 #include "cp-abi.h"
31
32 /* Local functions */
33
34 static void java_type_print_base (struct type * type,
35                                   struct ui_file *stream, int show,
36                                   int level);
37
38 static void
39 java_type_print_derivation_info (struct ui_file *stream, struct type *type)
40 {
41   char *name;
42   int i;
43   int n_bases;
44   int prev;
45
46   n_bases = TYPE_N_BASECLASSES (type);
47
48   for (i = 0, prev = 0; i < n_bases; i++)
49     {
50       int kind;
51
52       kind = BASETYPE_VIA_VIRTUAL (type, i) ? 'I' : 'E';
53
54       fputs_filtered (kind == prev ? ", "
55                       : kind == 'I' ? " implements "
56                       : " extends ",
57                       stream);
58       prev = kind;
59       name = type_name_no_tag (TYPE_BASECLASS (type, i));
60
61       fprintf_filtered (stream, "%s", name ? name : "(null)");
62     }
63
64   if (i > 0)
65     fputs_filtered (" ", stream);
66 }
67
68 /* Print the name of the type (or the ultimate pointer target,
69    function value or array element), or the description of a
70    structure or union.
71
72    SHOW positive means print details about the type (e.g. enum values),
73    and print structure elements passing SHOW - 1 for show.
74    SHOW negative means just print the type name or struct tag if there is one.
75    If there is no name, print something sensible but concise like
76    "struct {...}".
77    SHOW zero means just print the type name or struct tag if there is one.
78    If there is no name, print something sensible but not as concise like
79    "struct {int x; int y;}".
80
81    LEVEL is the number of spaces to indent by.
82    We increase it for some recursive calls.  */
83
84 static void
85 java_type_print_base (struct type *type, struct ui_file *stream, int show,
86                       int level)
87 {
88   int i;
89   int len;
90   char *mangled_name;
91   char *demangled_name;
92   QUIT;
93
94   wrap_here ("    ");
95
96   if (type == NULL)
97     {
98       fputs_filtered ("<type unknown>", stream);
99       return;
100     }
101
102   /* When SHOW is zero or less, and there is a valid type name, then always
103      just print the type name directly from the type.  */
104
105   if (show <= 0
106       && TYPE_NAME (type) != NULL)
107     {
108       fputs_filtered (TYPE_NAME (type), stream);
109       return;
110     }
111
112   CHECK_TYPEDEF (type);
113
114   switch (TYPE_CODE (type))
115     {
116     case TYPE_CODE_PTR:
117       java_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
118       break;
119
120     case TYPE_CODE_STRUCT:
121       if (TYPE_TAG_NAME (type) != NULL && TYPE_TAG_NAME (type)[0] == '[')
122         {                       /* array type */
123           char *name = java_demangle_type_signature (TYPE_TAG_NAME (type));
124           fputs_filtered (name, stream);
125           xfree (name);
126           break;
127         }
128
129       if (show >= 0)
130         fprintf_filtered (stream, "class ");
131
132       if (TYPE_TAG_NAME (type) != NULL)
133         {
134           fputs_filtered (TYPE_TAG_NAME (type), stream);
135           if (show > 0)
136             fputs_filtered (" ", stream);
137         }
138
139       wrap_here ("    ");
140
141       if (show < 0)
142         {
143           /* If we just printed a tag name, no need to print anything else.  */
144           if (TYPE_TAG_NAME (type) == NULL)
145             fprintf_filtered (stream, "{...}");
146         }
147       else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
148         {
149           java_type_print_derivation_info (stream, type);
150
151           fprintf_filtered (stream, "{\n");
152           if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
153             {
154               if (TYPE_STUB (type))
155                 fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
156               else
157                 fprintfi_filtered (level + 4, stream, "<no data fields>\n");
158             }
159
160           /* If there is a base class for this type,
161              do not print the field that it occupies.  */
162
163           len = TYPE_NFIELDS (type);
164           for (i = TYPE_N_BASECLASSES (type); i < len; i++)
165             {
166               QUIT;
167               /* Don't print out virtual function table.  */
168               if (strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5) == 0
169                   && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
170                 continue;
171
172               /* Don't print the dummy field "class". */
173               if (strncmp (TYPE_FIELD_NAME (type, i), "class", 5) == 0)
174                 continue;
175
176               print_spaces_filtered (level + 4, stream);
177
178               if (HAVE_CPLUS_STRUCT (type))
179                 {
180                   if (TYPE_FIELD_PROTECTED (type, i))
181                     fprintf_filtered (stream, "protected ");
182                   else if (TYPE_FIELD_PRIVATE (type, i))
183                     fprintf_filtered (stream, "private ");
184                   else
185                     fprintf_filtered (stream, "public ");
186                 }
187
188               if (field_is_static (&TYPE_FIELD (type, i)))
189                 fprintf_filtered (stream, "static ");
190
191               java_print_type (TYPE_FIELD_TYPE (type, i),
192                                TYPE_FIELD_NAME (type, i),
193                                stream, show - 1, level + 4);
194
195               fprintf_filtered (stream, ";\n");
196             }
197
198           /* If there are both fields and methods, put a space between. */
199           len = TYPE_NFN_FIELDS (type);
200           if (len)
201             fprintf_filtered (stream, "\n");
202
203           /* Print out the methods */
204
205           for (i = 0; i < len; i++)
206             {
207               struct fn_field *f;
208               int j;
209               char *method_name;
210               char *name;
211               int is_constructor;
212               int n_overloads;
213
214               f = TYPE_FN_FIELDLIST1 (type, i);
215               n_overloads = TYPE_FN_FIELDLIST_LENGTH (type, i);
216               method_name = TYPE_FN_FIELDLIST_NAME (type, i);
217               name = type_name_no_tag (type);
218               is_constructor = name && strcmp (method_name, name) == 0;
219
220               for (j = 0; j < n_overloads; j++)
221                 {
222                   char *physname;
223                   int is_full_physname_constructor;
224
225                   physname = TYPE_FN_FIELD_PHYSNAME (f, j);
226
227                   is_full_physname_constructor
228                     = (is_constructor_name (physname)
229                        || is_destructor_name (physname));
230
231                   QUIT;
232
233                   print_spaces_filtered (level + 4, stream);
234
235                   if (TYPE_FN_FIELD_PROTECTED (f, j))
236                     fprintf_filtered (stream, "protected ");
237                   else if (TYPE_FN_FIELD_PRIVATE (f, j))
238                     fprintf_filtered (stream, "private ");
239                   else if (TYPE_FN_FIELD_PUBLIC (f, j))
240                     fprintf_filtered (stream, "public ");
241
242                   if (TYPE_FN_FIELD_ABSTRACT (f, j))
243                     fprintf_filtered (stream, "abstract ");
244                   if (TYPE_FN_FIELD_STATIC (f, j))
245                     fprintf_filtered (stream, "static ");
246                   if (TYPE_FN_FIELD_FINAL (f, j))
247                     fprintf_filtered (stream, "final ");
248                   if (TYPE_FN_FIELD_SYNCHRONIZED (f, j))
249                     fprintf_filtered (stream, "synchronized ");
250                   if (TYPE_FN_FIELD_NATIVE (f, j))
251                     fprintf_filtered (stream, "native ");
252
253                   if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
254                     {
255                       /* Keep GDB from crashing here.  */
256                       fprintf_filtered (stream, "<undefined type> %s;\n",
257                                         TYPE_FN_FIELD_PHYSNAME (f, j));
258                       break;
259                     }
260                   else if (!is_constructor && !is_full_physname_constructor)
261                     {
262                       type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
263                                   "", stream, -1);
264                       fputs_filtered (" ", stream);
265                     }
266
267                   if (TYPE_FN_FIELD_STUB (f, j))
268                     /* Build something we can demangle.  */
269                     mangled_name = gdb_mangle_name (type, i, j);
270                   else
271                     mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j);
272
273                   demangled_name =
274                     cplus_demangle (mangled_name,
275                                     DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
276
277                   if (demangled_name == NULL)
278                     demangled_name = xstrdup (mangled_name);
279
280                   {
281                     char *demangled_no_class;
282                     char *ptr;
283
284                     ptr = demangled_no_class = demangled_name;
285
286                     while (1)
287                       {
288                         char c;
289
290                         c = *ptr++;
291
292                         if (c == 0 || c == '(')
293                           break;
294                         if (c == '.')
295                           demangled_no_class = ptr;
296                       }
297
298                     fputs_filtered (demangled_no_class, stream);
299                     xfree (demangled_name);
300                   }
301
302                   if (TYPE_FN_FIELD_STUB (f, j))
303                     xfree (mangled_name);
304
305                   fprintf_filtered (stream, ";\n");
306                 }
307             }
308
309           fprintfi_filtered (level, stream, "}");
310         }
311       break;
312
313     default:
314       c_type_print_base (type, stream, show, level);
315     }
316 }
317
318 /* LEVEL is the depth to indent lines by.  */
319
320 extern void c_type_print_varspec_suffix (struct type *, struct ui_file *,
321                                          int, int, int);
322
323 void
324 java_print_type (struct type *type, char *varstring, struct ui_file *stream,
325                  int show, int level)
326 {
327   int demangled_args;
328
329   java_type_print_base (type, stream, show, level);
330
331   if (varstring != NULL && *varstring != '\0')
332     {
333       fputs_filtered (" ", stream);
334       fputs_filtered (varstring, stream);
335     }
336
337   /* For demangled function names, we have the arglist as part of the name,
338      so don't print an additional pair of ()'s */
339
340   demangled_args = varstring != NULL && strchr (varstring, '(') != NULL;
341   c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
342 }