| /* Support for printing Fortran types for GDB, the GNU debugger. | 
 |  | 
 |    Copyright (C) 1986-2022 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 (type)->code () == TYPE_CODE_FUNC | 
 | 		      || (TYPE_TARGET_TYPE (type)->code () | 
 | 			  == TYPE_CODE_METHOD) | 
 | 		      || (TYPE_TARGET_TYPE (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 (type), stream, 0, 1); | 
 |       break; | 
 |  | 
 |     case TYPE_CODE_FUNC: | 
 |       f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); | 
 |       if (passed_a_ptr) | 
 | 	gdb_printf (stream, "("); | 
 |       break; | 
 |  | 
 |     case TYPE_CODE_ARRAY: | 
 |       f_type_print_varspec_prefix (TYPE_TARGET_TYPE (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) | 
 | 		&& PROP_CONST != TYPE_ASSOCIATED_PROP (type)->kind ()) | 
 | 	       || (TYPE_ALLOCATED_PROP (type) | 
 | 		   && PROP_CONST != TYPE_ALLOCATED_PROP (type)->kind ()) | 
 | 	       || (TYPE_DATA_LOCATION (type) | 
 | 		   && PROP_CONST != TYPE_DATA_LOCATION (type)->kind ())) | 
 | 	{ | 
 | 	  /* 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 (type)->code () == TYPE_CODE_ARRAY) | 
 | 	f_type_print_varspec_suffix (TYPE_TARGET_TYPE (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 (type)->code () != TYPE_CODE_ARRAY) | 
 | 	f_type_print_varspec_suffix (TYPE_TARGET_TYPE (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 (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 (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 (type), stream, 0, level); | 
 |       break; | 
 |  | 
 |     case TYPE_CODE_ARRAY: | 
 |       f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); | 
 |       break; | 
 |     case TYPE_CODE_FUNC: | 
 |       if (TYPE_TARGET_TYPE (type) == NULL) | 
 | 	type_print_unknown_return_type (stream); | 
 |       else | 
 | 	f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); | 
 |       break; | 
 |  | 
 |     case TYPE_CODE_PTR: | 
 |       gdb_printf (stream, "%*sPTR TO -> ( ", level, ""); | 
 |       f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0); | 
 |       break; | 
 |  | 
 |     case TYPE_CODE_REF: | 
 |       gdb_printf (stream, "%*sREF TO -> ( ", level, ""); | 
 |       f_type_print_base (TYPE_TARGET_TYPE (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.kind () == PROP_CONST) | 
 | 	{ | 
 | 	  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"); | 
 | } |