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