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