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