| /* Support for printing Fortran types for GDB, the GNU debugger. | |
| Copyright (C) 1986-2023 Free Software Foundation, Inc. | |
| Contributed by Motorola. Adapted from the C version by Farooq Butt | |
| (fmbutt@engage.sps.mot.com). | |
| This file is part of GDB. | |
| This program is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 3 of the License, or | |
| (at your option) any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
| #include "defs.h" | |
| #include "gdbsupport/gdb_obstack.h" | |
| #include "bfd.h" | |
| #include "symtab.h" | |
| #include "gdbtypes.h" | |
| #include "expression.h" | |
| #include "value.h" | |
| #include "gdbcore.h" | |
| #include "target.h" | |
| #include "f-lang.h" | |
| #include "typeprint.h" | |
| #include "cli/cli-style.h" | |
| /* See f-lang.h. */ | |
| void | |
| f_language::print_typedef (struct type *type, struct symbol *new_symbol, | |
| struct ui_file *stream) const | |
| { | |
| type = check_typedef (type); | |
| print_type (type, "", stream, 0, 0, &type_print_raw_options); | |
| } | |
| /* See f-lang.h. */ | |
| void | |
| f_language::print_type (struct type *type, const char *varstring, | |
| struct ui_file *stream, int show, int level, | |
| const struct type_print_options *flags) const | |
| { | |
| enum type_code code; | |
| f_type_print_base (type, stream, show, level); | |
| code = type->code (); | |
| if ((varstring != NULL && *varstring != '\0') | |
| /* Need a space if going to print stars or brackets; but not if we | |
| will print just a type name. */ | |
| || ((show > 0 | |
| || type->name () == 0) | |
| && (code == TYPE_CODE_FUNC | |
| || code == TYPE_CODE_METHOD | |
| || code == TYPE_CODE_ARRAY | |
| || ((code == TYPE_CODE_PTR | |
| || code == TYPE_CODE_REF) | |
| && (type->target_type ()->code () == TYPE_CODE_FUNC | |
| || (type->target_type ()->code () | |
| == TYPE_CODE_METHOD) | |
| || (type->target_type ()->code () | |
| == TYPE_CODE_ARRAY)))))) | |
| gdb_puts (" ", stream); | |
| f_type_print_varspec_prefix (type, stream, show, 0); | |
| if (varstring != NULL) | |
| { | |
| int demangled_args; | |
| gdb_puts (varstring, stream); | |
| /* For demangled function names, we have the arglist as part of the name, | |
| so don't print an additional pair of ()'s. */ | |
| demangled_args = (*varstring != '\0' | |
| && varstring[strlen (varstring) - 1] == ')'); | |
| f_type_print_varspec_suffix (type, stream, show, 0, demangled_args, 0, false); | |
| } | |
| } | |
| /* See f-lang.h. */ | |
| void | |
| f_language::f_type_print_varspec_prefix (struct type *type, | |
| struct ui_file *stream, | |
| int show, int passed_a_ptr) const | |
| { | |
| if (type == 0) | |
| return; | |
| if (type->name () && show <= 0) | |
| return; | |
| QUIT; | |
| switch (type->code ()) | |
| { | |
| case TYPE_CODE_PTR: | |
| f_type_print_varspec_prefix (type->target_type (), stream, 0, 1); | |
| break; | |
| case TYPE_CODE_FUNC: | |
| f_type_print_varspec_prefix (type->target_type (), stream, 0, 0); | |
| if (passed_a_ptr) | |
| gdb_printf (stream, "("); | |
| break; | |
| case TYPE_CODE_ARRAY: | |
| f_type_print_varspec_prefix (type->target_type (), stream, 0, 0); | |
| break; | |
| case TYPE_CODE_UNDEF: | |
| case TYPE_CODE_STRUCT: | |
| case TYPE_CODE_UNION: | |
| case TYPE_CODE_NAMELIST: | |
| case TYPE_CODE_ENUM: | |
| case TYPE_CODE_INT: | |
| case TYPE_CODE_FLT: | |
| case TYPE_CODE_VOID: | |
| case TYPE_CODE_ERROR: | |
| case TYPE_CODE_CHAR: | |
| case TYPE_CODE_BOOL: | |
| case TYPE_CODE_SET: | |
| case TYPE_CODE_RANGE: | |
| case TYPE_CODE_STRING: | |
| case TYPE_CODE_METHOD: | |
| case TYPE_CODE_REF: | |
| case TYPE_CODE_COMPLEX: | |
| case TYPE_CODE_TYPEDEF: | |
| /* These types need no prefix. They are listed here so that | |
| gcc -Wall will reveal any types that haven't been handled. */ | |
| break; | |
| } | |
| } | |
| /* See f-lang.h. */ | |
| void | |
| f_language::f_type_print_varspec_suffix (struct type *type, | |
| struct ui_file *stream, | |
| int show, int passed_a_ptr, | |
| int demangled_args, | |
| int arrayprint_recurse_level, | |
| bool print_rank_only) const | |
| { | |
| /* No static variables are permitted as an error call may occur during | |
| execution of this function. */ | |
| if (type == 0) | |
| return; | |
| if (type->name () && show <= 0) | |
| return; | |
| QUIT; | |
| switch (type->code ()) | |
| { | |
| case TYPE_CODE_ARRAY: | |
| arrayprint_recurse_level++; | |
| if (arrayprint_recurse_level == 1) | |
| gdb_printf (stream, "("); | |
| if (type_not_associated (type)) | |
| print_rank_only = true; | |
| else if (type_not_allocated (type)) | |
| print_rank_only = true; | |
| else if ((TYPE_ASSOCIATED_PROP (type) | |
| && !TYPE_ASSOCIATED_PROP (type)->is_constant ()) | |
| || (TYPE_ALLOCATED_PROP (type) | |
| && !TYPE_ALLOCATED_PROP (type)->is_constant ()) | |
| || (TYPE_DATA_LOCATION (type) | |
| && !TYPE_DATA_LOCATION (type)->is_constant ())) | |
| { | |
| /* This case exist when we ptype a typename which has the dynamic | |
| properties but cannot be resolved as there is no object. */ | |
| print_rank_only = true; | |
| } | |
| if (type->target_type ()->code () == TYPE_CODE_ARRAY) | |
| f_type_print_varspec_suffix (type->target_type (), stream, 0, | |
| 0, 0, arrayprint_recurse_level, | |
| print_rank_only); | |
| if (print_rank_only) | |
| gdb_printf (stream, ":"); | |
| else | |
| { | |
| LONGEST lower_bound = f77_get_lowerbound (type); | |
| if (lower_bound != 1) /* Not the default. */ | |
| gdb_printf (stream, "%s:", plongest (lower_bound)); | |
| /* Make sure that, if we have an assumed size array, we | |
| print out a warning and print the upperbound as '*'. */ | |
| if (type->bounds ()->high.kind () == PROP_UNDEFINED) | |
| gdb_printf (stream, "*"); | |
| else | |
| { | |
| LONGEST upper_bound = f77_get_upperbound (type); | |
| gdb_puts (plongest (upper_bound), stream); | |
| } | |
| } | |
| if (type->target_type ()->code () != TYPE_CODE_ARRAY) | |
| f_type_print_varspec_suffix (type->target_type (), stream, 0, | |
| 0, 0, arrayprint_recurse_level, | |
| print_rank_only); | |
| if (arrayprint_recurse_level == 1) | |
| gdb_printf (stream, ")"); | |
| else | |
| gdb_printf (stream, ","); | |
| arrayprint_recurse_level--; | |
| break; | |
| case TYPE_CODE_PTR: | |
| case TYPE_CODE_REF: | |
| f_type_print_varspec_suffix (type->target_type (), stream, 0, 1, 0, | |
| arrayprint_recurse_level, false); | |
| gdb_printf (stream, " )"); | |
| break; | |
| case TYPE_CODE_FUNC: | |
| { | |
| int i, nfields = type->num_fields (); | |
| f_type_print_varspec_suffix (type->target_type (), stream, 0, | |
| passed_a_ptr, 0, | |
| arrayprint_recurse_level, false); | |
| if (passed_a_ptr) | |
| gdb_printf (stream, ") "); | |
| gdb_printf (stream, "("); | |
| if (nfields == 0 && type->is_prototyped ()) | |
| print_type (builtin_f_type (type->arch ())->builtin_void, | |
| "", stream, -1, 0, 0); | |
| else | |
| for (i = 0; i < nfields; i++) | |
| { | |
| if (i > 0) | |
| { | |
| gdb_puts (", ", stream); | |
| stream->wrap_here (4); | |
| } | |
| print_type (type->field (i).type (), "", stream, -1, 0, 0); | |
| } | |
| gdb_printf (stream, ")"); | |
| } | |
| break; | |
| case TYPE_CODE_UNDEF: | |
| case TYPE_CODE_STRUCT: | |
| case TYPE_CODE_UNION: | |
| case TYPE_CODE_NAMELIST: | |
| case TYPE_CODE_ENUM: | |
| case TYPE_CODE_INT: | |
| case TYPE_CODE_FLT: | |
| case TYPE_CODE_VOID: | |
| case TYPE_CODE_ERROR: | |
| case TYPE_CODE_CHAR: | |
| case TYPE_CODE_BOOL: | |
| case TYPE_CODE_SET: | |
| case TYPE_CODE_RANGE: | |
| case TYPE_CODE_STRING: | |
| case TYPE_CODE_METHOD: | |
| case TYPE_CODE_COMPLEX: | |
| case TYPE_CODE_TYPEDEF: | |
| /* These types do not need a suffix. They are listed so that | |
| gcc -Wall will report types that may not have been considered. */ | |
| break; | |
| } | |
| } | |
| /* See f-lang.h. */ | |
| void | |
| f_language::f_type_print_derivation_info (struct type *type, | |
| struct ui_file *stream) const | |
| { | |
| /* Fortran doesn't support multiple inheritance. */ | |
| const int i = 0; | |
| if (TYPE_N_BASECLASSES (type) > 0) | |
| gdb_printf (stream, ", extends(%s) ::", TYPE_BASECLASS (type, i)->name ()); | |
| } | |
| /* See f-lang.h. */ | |
| void | |
| f_language::f_type_print_base (struct type *type, struct ui_file *stream, | |
| int show, int level) const | |
| { | |
| int index; | |
| QUIT; | |
| stream->wrap_here (4); | |
| if (type == NULL) | |
| { | |
| fputs_styled ("<type unknown>", metadata_style.style (), stream); | |
| return; | |
| } | |
| /* When SHOW is zero or less, and there is a valid type name, then always | |
| just print the type name directly from the type. */ | |
| if ((show <= 0) && (type->name () != NULL)) | |
| { | |
| const char *prefix = ""; | |
| if (type->code () == TYPE_CODE_UNION) | |
| prefix = "Type, C_Union :: "; | |
| else if (type->code () == TYPE_CODE_STRUCT | |
| || type->code () == TYPE_CODE_NAMELIST) | |
| prefix = "Type "; | |
| gdb_printf (stream, "%*s%s%s", level, "", prefix, type->name ()); | |
| return; | |
| } | |
| if (type->code () != TYPE_CODE_TYPEDEF) | |
| type = check_typedef (type); | |
| switch (type->code ()) | |
| { | |
| case TYPE_CODE_TYPEDEF: | |
| f_type_print_base (type->target_type (), stream, 0, level); | |
| break; | |
| case TYPE_CODE_ARRAY: | |
| f_type_print_base (type->target_type (), stream, show, level); | |
| break; | |
| case TYPE_CODE_FUNC: | |
| if (type->target_type () == NULL) | |
| type_print_unknown_return_type (stream); | |
| else | |
| f_type_print_base (type->target_type (), stream, show, level); | |
| break; | |
| case TYPE_CODE_PTR: | |
| gdb_printf (stream, "%*sPTR TO -> ( ", level, ""); | |
| f_type_print_base (type->target_type (), stream, show, 0); | |
| break; | |
| case TYPE_CODE_REF: | |
| gdb_printf (stream, "%*sREF TO -> ( ", level, ""); | |
| f_type_print_base (type->target_type (), stream, show, 0); | |
| break; | |
| case TYPE_CODE_VOID: | |
| { | |
| struct type *void_type = builtin_f_type (type->arch ())->builtin_void; | |
| gdb_printf (stream, "%*s%s", level, "", void_type->name ()); | |
| } | |
| break; | |
| case TYPE_CODE_UNDEF: | |
| gdb_printf (stream, "%*sstruct <unknown>", level, ""); | |
| break; | |
| case TYPE_CODE_ERROR: | |
| gdb_printf (stream, "%*s%s", level, "", TYPE_ERROR_NAME (type)); | |
| break; | |
| case TYPE_CODE_RANGE: | |
| /* This should not occur. */ | |
| gdb_printf (stream, "%*s<range type>", level, ""); | |
| break; | |
| case TYPE_CODE_CHAR: | |
| case TYPE_CODE_INT: | |
| /* There may be some character types that attempt to come | |
| through as TYPE_CODE_INT since dbxstclass.h is so | |
| C-oriented, we must change these to "character" from "char". */ | |
| if (strcmp (type->name (), "char") == 0) | |
| gdb_printf (stream, "%*scharacter", level, ""); | |
| else | |
| goto default_case; | |
| break; | |
| case TYPE_CODE_STRING: | |
| /* Strings may have dynamic upperbounds (lengths) like arrays. We | |
| check specifically for the PROP_CONST case to indicate that the | |
| dynamic type has been resolved. If we arrive here having been | |
| asked to print the type of a value with a dynamic type then the | |
| bounds will not have been resolved. */ | |
| if (type->bounds ()->high.is_constant ()) | |
| { | |
| LONGEST upper_bound = f77_get_upperbound (type); | |
| gdb_printf (stream, "character*%s", pulongest (upper_bound)); | |
| } | |
| else | |
| gdb_printf (stream, "%*scharacter*(*)", level, ""); | |
| break; | |
| case TYPE_CODE_STRUCT: | |
| case TYPE_CODE_UNION: | |
| case TYPE_CODE_NAMELIST: | |
| if (type->code () == TYPE_CODE_UNION) | |
| gdb_printf (stream, "%*sType, C_Union ::", level, ""); | |
| else | |
| gdb_printf (stream, "%*sType", level, ""); | |
| if (show > 0) | |
| f_type_print_derivation_info (type, stream); | |
| gdb_puts (" ", stream); | |
| gdb_puts (type->name (), stream); | |
| /* According to the definition, | |
| we only print structure elements in case show > 0. */ | |
| if (show > 0) | |
| { | |
| gdb_puts ("\n", stream); | |
| for (index = 0; index < type->num_fields (); index++) | |
| { | |
| f_type_print_base (type->field (index).type (), stream, | |
| show - 1, level + 4); | |
| gdb_puts (" :: ", stream); | |
| fputs_styled (type->field (index).name (), | |
| variable_name_style.style (), stream); | |
| f_type_print_varspec_suffix (type->field (index).type (), | |
| stream, show - 1, 0, 0, 0, false); | |
| gdb_puts ("\n", stream); | |
| } | |
| gdb_printf (stream, "%*sEnd Type ", level, ""); | |
| gdb_puts (type->name (), stream); | |
| } | |
| break; | |
| case TYPE_CODE_MODULE: | |
| gdb_printf (stream, "%*smodule %s", level, "", type->name ()); | |
| break; | |
| default_case: | |
| default: | |
| /* Handle types not explicitly handled by the other cases, | |
| such as fundamental types. For these, just print whatever | |
| the type name is, as recorded in the type itself. If there | |
| is no type name, then complain. */ | |
| if (type->name () != NULL) | |
| gdb_printf (stream, "%*s%s", level, "", type->name ()); | |
| else | |
| error (_("Invalid type code (%d) in symbol table."), type->code ()); | |
| break; | |
| } | |
| if (TYPE_IS_ALLOCATABLE (type)) | |
| gdb_printf (stream, ", allocatable"); | |
| } |