X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ff-lang.c;h=90a794ef4bab10a3c940e767777bd4e5d6e72147;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=d63becdac3c1dc54d2cab92c4615ebc3baaaca56;hpb=7b6bb8daaceb9ecf3f42dea57ae82733d6a3b2f6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/f-lang.c b/gdb/f-lang.c index d63becdac3..90a794ef4b 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -1,7 +1,6 @@ /* Fortran language support routines for GDB, the GNU debugger. - Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1993-2020 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C parser by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -22,58 +21,56 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_string.h" #include "symtab.h" #include "gdbtypes.h" #include "expression.h" #include "parser-defs.h" #include "language.h" +#include "varobj.h" +#include "gdbcore.h" #include "f-lang.h" #include "valprint.h" #include "value.h" #include "cp-support.h" +#include "charset.h" +#include "c-lang.h" +#include "target-float.h" +#include "gdbarch.h" +#include -/* Following is dubious stuff that had been in the xcoff reader. */ - -struct saved_fcn - { - long line_offset; /* Line offset for function */ - struct saved_fcn *next; - }; +/* Local functions */ +static void f_printchar (int c, struct type *type, struct ui_file * stream); +static void f_emit_char (int c, struct type *type, + struct ui_file * stream, int quoter); -struct saved_bf_symnum - { - long symnum_fcn; /* Symnum of function (i.e. .function directive) */ - long symnum_bf; /* Symnum of .bf for this function */ - struct saved_bf_symnum *next; - }; +/* Return the encoding that should be used for the character type + TYPE. */ -typedef struct saved_fcn SAVED_FUNCTION, *SAVED_FUNCTION_PTR; -typedef struct saved_bf_symnum SAVED_BF, *SAVED_BF_PTR; +static const char * +f_get_encoding (struct type *type) +{ + const char *encoding; -/* Local functions */ + switch (TYPE_LENGTH (type)) + { + case 1: + encoding = target_charset (get_type_arch (type)); + break; + case 4: + if (type_byte_order (type) == BFD_ENDIAN_BIG) + encoding = "UTF-32BE"; + else + encoding = "UTF-32LE"; + break; -extern void _initialize_f_language (void); -#if 0 -static void clear_function_list (void); -static long get_bf_for_fcn (long); -static void clear_bf_list (void); -static void patch_all_commons_by_name (char *, CORE_ADDR, int); -static SAVED_F77_COMMON_PTR find_first_common_named (char *); -static void add_common_entry (struct symbol *); -static void add_common_block (char *, CORE_ADDR, int, char *); -static SAVED_FUNCTION *allocate_saved_function_node (void); -static SAVED_BF_PTR allocate_saved_bf_node (void); -static COMMON_ENTRY_PTR allocate_common_entry_node (void); -static SAVED_F77_COMMON_PTR allocate_saved_f77_common_node (void); -static void patch_common_entries (SAVED_F77_COMMON_PTR, CORE_ADDR, int); -#endif + default: + error (_("unrecognized character type")); + } -static void f_printchar (int c, struct type *type, struct ui_file * stream); -static void f_emit_char (int c, struct type *type, - struct ui_file * stream, int quoter); + return encoding; +} /* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. Note that that format for printing @@ -84,48 +81,12 @@ static void f_emit_char (int c, struct type *type, static void f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) { - c &= 0xFF; /* Avoid sign bit follies */ + const char *encoding = f_get_encoding (type); - if (PRINT_LITERAL_FORM (c)) - { - if (c == '\\' || c == quoter) - fputs_filtered ("\\", stream); - fprintf_filtered (stream, "%c", c); - } - else - { - switch (c) - { - case '\n': - fputs_filtered ("\\n", stream); - break; - case '\b': - fputs_filtered ("\\b", stream); - break; - case '\t': - fputs_filtered ("\\t", stream); - break; - case '\f': - fputs_filtered ("\\f", stream); - break; - case '\r': - fputs_filtered ("\\r", stream); - break; - case '\033': - fputs_filtered ("\\e", stream); - break; - case '\007': - fputs_filtered ("\\a", stream); - break; - default: - fprintf_filtered (stream, "\\%.3o", (unsigned int) c); - break; - } - } + generic_emit_char (c, type, stream, quoter, encoding); } -/* FIXME: This is a copy of the same function from c-exp.y. It should - be replaced with a true F77version. */ +/* Implementation of la_printchar. */ static void f_printchar (int c, struct type *type, struct ui_file *stream) @@ -140,90 +101,23 @@ f_printchar (int c, struct type *type, struct ui_file *stream) are printed as appropriate. Print ellipses at the end if we had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. FIXME: This is a copy of the same function from c-exp.y. It should - be replaced with a true F77 version. */ + be replaced with a true F77 version. */ static void f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, unsigned int length, const char *encoding, int force_ellipses, const struct value_print_options *options) { - unsigned int i; - unsigned int things_printed = 0; - int in_quotes = 0; - int need_comma = 0; - - if (length == 0) - { - fputs_filtered ("''", gdb_stdout); - return; - } + const char *type_encoding = f_get_encoding (type); - for (i = 0; i < length && things_printed < options->print_max; ++i) - { - /* Position of the character we are examining - to see whether it is repeated. */ - unsigned int rep1; - /* Number of repetitions we have detected so far. */ - unsigned int reps; + if (TYPE_LENGTH (type) == 4) + fputs_filtered ("4_", stream); - QUIT; + if (!encoding || !*encoding) + encoding = type_encoding; - if (need_comma) - { - fputs_filtered (", ", stream); - need_comma = 0; - } - - rep1 = i + 1; - reps = 1; - while (rep1 < length && string[rep1] == string[i]) - { - ++rep1; - ++reps; - } - - if (reps > options->repeat_count_threshold) - { - if (in_quotes) - { - if (options->inspect_it) - fputs_filtered ("\\', ", stream); - else - fputs_filtered ("', ", stream); - in_quotes = 0; - } - f_printchar (string[i], type, stream); - fprintf_filtered (stream, " ", reps); - i = rep1 - 1; - things_printed += options->repeat_count_threshold; - need_comma = 1; - } - else - { - if (!in_quotes) - { - if (options->inspect_it) - fputs_filtered ("\\'", stream); - else - fputs_filtered ("'", stream); - in_quotes = 1; - } - LA_EMIT_CHAR (string[i], type, stream, '"'); - ++things_printed; - } - } - - /* Terminate the quotes if necessary. */ - if (in_quotes) - { - if (options->inspect_it) - fputs_filtered ("\\'", stream); - else - fputs_filtered ("'", stream); - } - - if (force_ellipses || i < length) - fputs_filtered ("...", stream); + generic_printstr (stream, type, string, length, encoding, + force_ellipses, '\'', 0, options); } @@ -251,7 +145,7 @@ static const struct op_print f_op_print_tab[] = {".LT.", BINOP_LESS, PREC_ORDER, 0}, {"**", UNOP_IND, PREC_PREFIX, 0}, {"@", BINOP_REPEAT, PREC_REPEAT, 0}, - {NULL, 0, 0, 0} + {NULL, OP_NULL, PREC_REPEAT, 0} }; enum f_primitive_types { @@ -271,47 +165,9 @@ enum f_primitive_types { nr_f_primitive_types }; -static void -f_language_arch_info (struct gdbarch *gdbarch, - struct language_arch_info *lai) -{ - const struct builtin_f_type *builtin = builtin_f_type (gdbarch); - - lai->string_char_type = builtin->builtin_character; - lai->primitive_type_vector - = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_f_primitive_types + 1, - struct type *); - - lai->primitive_type_vector [f_primitive_type_character] - = builtin->builtin_character; - lai->primitive_type_vector [f_primitive_type_logical] - = builtin->builtin_logical; - lai->primitive_type_vector [f_primitive_type_logical_s1] - = builtin->builtin_logical_s1; - lai->primitive_type_vector [f_primitive_type_logical_s2] - = builtin->builtin_logical_s2; - lai->primitive_type_vector [f_primitive_type_logical_s8] - = builtin->builtin_logical_s8; - lai->primitive_type_vector [f_primitive_type_real] - = builtin->builtin_real; - lai->primitive_type_vector [f_primitive_type_real_s8] - = builtin->builtin_real_s8; - lai->primitive_type_vector [f_primitive_type_real_s16] - = builtin->builtin_real_s16; - lai->primitive_type_vector [f_primitive_type_complex_s8] - = builtin->builtin_complex_s8; - lai->primitive_type_vector [f_primitive_type_complex_s16] - = builtin->builtin_complex_s16; - lai->primitive_type_vector [f_primitive_type_void] - = builtin->builtin_void; - - lai->bool_type_symbol = "logical"; - lai->bool_type_default = builtin->builtin_logical_s2; -} - /* Remove the modules separator :: from the default break list. */ -static char * +static const char * f_word_break_characters (void) { static char *retval; @@ -333,519 +189,645 @@ f_word_break_characters (void) return retval; } -/* Consider the modules separator :: as a valid symbol name character class. */ +/* Consider the modules separator :: as a valid symbol name character + class. */ -static char ** -f_make_symbol_completion_list (char *text, char *word) +static void +f_collect_symbol_completion_matches (completion_tracker &tracker, + complete_symbol_mode mode, + symbol_name_match_type compare_name, + const char *text, const char *word, + enum type_code code) { - return default_make_symbol_completion_list_break_on (text, word, ":"); + default_collect_symbol_completion_matches_break_on (tracker, mode, + compare_name, + text, word, ":", code); } -/* This is declared in c-lang.h but it is silly to import that file for what - is already just a hack. */ -extern int c_value_print (struct value *, struct ui_file *, - const struct value_print_options *); - -const struct language_defn f_language_defn = -{ - "fortran", - language_fortran, - range_check_on, - type_check_on, - case_sensitive_off, - array_column_major, - macro_expansion_no, - &exp_descriptor_standard, - f_parse, /* parser */ - f_error, /* parser error function */ - null_post_parser, - f_printchar, /* Print character constant */ - f_printstr, /* function to print string constant */ - f_emit_char, /* Function to print a single character */ - f_print_type, /* Print a type using appropriate syntax */ - default_print_typedef, /* Print a typedef using appropriate syntax */ - f_val_print, /* Print a value using appropriate syntax */ - c_value_print, /* FIXME */ - NULL, /* Language specific skip_trampoline */ - NULL, /* name_of_this */ - cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ - basic_lookup_transparent_type,/* lookup_transparent_type */ - NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ - f_op_print_tab, /* expression operators for printing */ - 0, /* arrays are first-class (not c-style) */ - 1, /* String lower bound */ - f_word_break_characters, - f_make_symbol_completion_list, - f_language_arch_info, - default_print_array_index, - default_pass_by_reference, - default_get_string, - LANG_MAGIC -}; +/* Special expression evaluation cases for Fortran. */ -static void * -build_fortran_types (struct gdbarch *gdbarch) +static struct value * +evaluate_subexp_f (struct type *expect_type, struct expression *exp, + int *pos, enum noside noside) { - struct builtin_f_type *builtin_f_type - = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_f_type); + struct value *arg1 = NULL, *arg2 = NULL; + enum exp_opcode op; + int pc; + struct type *type; - builtin_f_type->builtin_void - = arch_type (gdbarch, TYPE_CODE_VOID, 1, "VOID"); - - builtin_f_type->builtin_character - = arch_integer_type (gdbarch, TARGET_CHAR_BIT, 0, "character"); + pc = *pos; + *pos += 1; + op = exp->elts[pc].opcode; - builtin_f_type->builtin_logical_s1 - = arch_boolean_type (gdbarch, TARGET_CHAR_BIT, 1, "logical*1"); - - builtin_f_type->builtin_integer_s2 - = arch_integer_type (gdbarch, gdbarch_short_bit (gdbarch), 0, - "integer*2"); - - builtin_f_type->builtin_logical_s2 - = arch_boolean_type (gdbarch, gdbarch_short_bit (gdbarch), 1, - "logical*2"); - - builtin_f_type->builtin_logical_s8 - = arch_boolean_type (gdbarch, gdbarch_long_long_bit (gdbarch), 1, - "logical*8"); + switch (op) + { + default: + *pos -= 1; + return evaluate_subexp_standard (expect_type, exp, pos, noside); + + case UNOP_ABS: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + type = value_type (arg1); + switch (type->code ()) + { + case TYPE_CODE_FLT: + { + double d + = fabs (target_float_to_host_double (value_contents (arg1), + value_type (arg1))); + return value_from_host_double (type, d); + } + case TYPE_CODE_INT: + { + LONGEST l = value_as_long (arg1); + l = llabs (l); + return value_from_longest (type, l); + } + } + error (_("ABS of type %s not supported"), TYPE_SAFE_NAME (type)); + + case BINOP_MOD: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + type = value_type (arg1); + if (type->code () != value_type (arg2)->code ()) + error (_("non-matching types for parameters to MOD ()")); + switch (type->code ()) + { + case TYPE_CODE_FLT: + { + double d1 + = target_float_to_host_double (value_contents (arg1), + value_type (arg1)); + double d2 + = target_float_to_host_double (value_contents (arg2), + value_type (arg2)); + double d3 = fmod (d1, d2); + return value_from_host_double (type, d3); + } + case TYPE_CODE_INT: + { + LONGEST v1 = value_as_long (arg1); + LONGEST v2 = value_as_long (arg2); + if (v2 == 0) + error (_("calling MOD (N, 0) is undefined")); + LONGEST v3 = v1 - (v1 / v2) * v2; + return value_from_longest (value_type (arg1), v3); + } + } + error (_("MOD of type %s not supported"), TYPE_SAFE_NAME (type)); - builtin_f_type->builtin_integer - = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 0, - "integer"); + case UNOP_FORTRAN_CEILING: + { + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + type = value_type (arg1); + if (type->code () != TYPE_CODE_FLT) + error (_("argument to CEILING must be of type float")); + double val + = target_float_to_host_double (value_contents (arg1), + value_type (arg1)); + val = ceil (val); + return value_from_host_double (type, val); + } - builtin_f_type->builtin_logical - = arch_boolean_type (gdbarch, gdbarch_int_bit (gdbarch), 1, - "logical*4"); + case UNOP_FORTRAN_FLOOR: + { + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + type = value_type (arg1); + if (type->code () != TYPE_CODE_FLT) + error (_("argument to FLOOR must be of type float")); + double val + = target_float_to_host_double (value_contents (arg1), + value_type (arg1)); + val = floor (val); + return value_from_host_double (type, val); + } - builtin_f_type->builtin_real - = arch_float_type (gdbarch, gdbarch_float_bit (gdbarch), - "real", NULL); - builtin_f_type->builtin_real_s8 - = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch), - "real*8", NULL); - builtin_f_type->builtin_real_s16 - = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch), - "real*16", NULL); + case BINOP_FORTRAN_MODULO: + { + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + type = value_type (arg1); + if (type->code () != value_type (arg2)->code ()) + error (_("non-matching types for parameters to MODULO ()")); + /* MODULO(A, P) = A - FLOOR (A / P) * P */ + switch (type->code ()) + { + case TYPE_CODE_INT: + { + LONGEST a = value_as_long (arg1); + LONGEST p = value_as_long (arg2); + LONGEST result = a - (a / p) * p; + if (result != 0 && (a < 0) != (p < 0)) + result += p; + return value_from_longest (value_type (arg1), result); + } + case TYPE_CODE_FLT: + { + double a + = target_float_to_host_double (value_contents (arg1), + value_type (arg1)); + double p + = target_float_to_host_double (value_contents (arg2), + value_type (arg2)); + double result = fmod (a, p); + if (result != 0 && (a < 0.0) != (p < 0.0)) + result += p; + return value_from_host_double (type, result); + } + } + error (_("MODULO of type %s not supported"), TYPE_SAFE_NAME (type)); + } - builtin_f_type->builtin_complex_s8 - = arch_complex_type (gdbarch, "complex*8", - builtin_f_type->builtin_real); - builtin_f_type->builtin_complex_s16 - = arch_complex_type (gdbarch, "complex*16", - builtin_f_type->builtin_real_s8); - builtin_f_type->builtin_complex_s32 - = arch_complex_type (gdbarch, "complex*32", - builtin_f_type->builtin_real_s16); + case BINOP_FORTRAN_CMPLX: + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); + if (noside == EVAL_SKIP) + return eval_skip_value (exp); + type = builtin_f_type(exp->gdbarch)->builtin_complex_s16; + return value_literal_complex (arg1, arg2, type); + + case UNOP_FORTRAN_KIND: + arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); + type = value_type (arg1); + + switch (type->code ()) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_MODULE: + case TYPE_CODE_FUNC: + error (_("argument to kind must be an intrinsic type")); + } + + if (!TYPE_TARGET_TYPE (type)) + return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, + TYPE_LENGTH (type)); + return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, + TYPE_LENGTH (TYPE_TARGET_TYPE (type))); + } - return builtin_f_type; + /* Should be unreachable. */ + return nullptr; } -static struct gdbarch_data *f_type_data; +/* Return true if TYPE is a string. */ -const struct builtin_f_type * -builtin_f_type (struct gdbarch *gdbarch) +static bool +f_is_string_type_p (struct type *type) { - return gdbarch_data (gdbarch, f_type_data); + type = check_typedef (type); + return (type->code () == TYPE_CODE_STRING + || (type->code () == TYPE_CODE_ARRAY + && TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_CHAR)); } -void -_initialize_f_language (void) -{ - f_type_data = gdbarch_data_register_post_init (build_fortran_types); +/* Special expression lengths for Fortran. */ - add_language (&f_language_defn); -} - -#if 0 -static SAVED_BF_PTR -allocate_saved_bf_node (void) +static void +operator_length_f (const struct expression *exp, int pc, int *oplenp, + int *argsp) { - SAVED_BF_PTR new; + int oplen = 1; + int args = 0; - new = (SAVED_BF_PTR) xmalloc (sizeof (SAVED_BF)); - return (new); -} + switch (exp->elts[pc - 1].opcode) + { + default: + operator_length_standard (exp, pc, oplenp, argsp); + return; -static SAVED_FUNCTION * -allocate_saved_function_node (void) -{ - SAVED_FUNCTION *new; + case UNOP_FORTRAN_KIND: + case UNOP_FORTRAN_FLOOR: + case UNOP_FORTRAN_CEILING: + oplen = 1; + args = 1; + break; + + case BINOP_FORTRAN_CMPLX: + case BINOP_FORTRAN_MODULO: + oplen = 1; + args = 2; + break; + } - new = (SAVED_FUNCTION *) xmalloc (sizeof (SAVED_FUNCTION)); - return (new); + *oplenp = oplen; + *argsp = args; } -static SAVED_F77_COMMON_PTR -allocate_saved_f77_common_node (void) -{ - SAVED_F77_COMMON_PTR new; +/* Helper for PRINT_SUBEXP_F. Arguments are as for PRINT_SUBEXP_F, except + the extra argument NAME which is the text that should be printed as the + name of this operation. */ - new = (SAVED_F77_COMMON_PTR) xmalloc (sizeof (SAVED_F77_COMMON)); - return (new); -} - -static COMMON_ENTRY_PTR -allocate_common_entry_node (void) +static void +print_unop_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec, + const char *name) { - COMMON_ENTRY_PTR new; - - new = (COMMON_ENTRY_PTR) xmalloc (sizeof (COMMON_ENTRY)); - return (new); + (*pos)++; + fprintf_filtered (stream, "%s(", name); + print_subexp (exp, pos, stream, PREC_SUFFIX); + fputs_filtered (")", stream); } -#endif - -SAVED_F77_COMMON_PTR head_common_list = NULL; /* Ptr to 1st saved COMMON */ -SAVED_F77_COMMON_PTR tail_common_list = NULL; /* Ptr to last saved COMMON */ -SAVED_F77_COMMON_PTR current_common = NULL; /* Ptr to current COMMON */ -#if 0 -static SAVED_BF_PTR saved_bf_list = NULL; /* Ptr to (.bf,function) - list */ -static SAVED_BF_PTR saved_bf_list_end = NULL; /* Ptr to above list's end */ -static SAVED_BF_PTR current_head_bf_list = NULL; /* Current head of above list - */ - -static SAVED_BF_PTR tmp_bf_ptr; /* Generic temporary for use - in macros */ - -/* The following function simply enters a given common block onto - the global common block chain */ +/* Helper for PRINT_SUBEXP_F. Arguments are as for PRINT_SUBEXP_F, except + the extra argument NAME which is the text that should be printed as the + name of this operation. */ static void -add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) +print_binop_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec, + const char *name) { - SAVED_F77_COMMON_PTR tmp; - char *c, *local_copy_func_stab; + (*pos)++; + fprintf_filtered (stream, "%s(", name); + print_subexp (exp, pos, stream, PREC_SUFFIX); + fputs_filtered (",", stream); + print_subexp (exp, pos, stream, PREC_SUFFIX); + fputs_filtered (")", stream); +} - /* If the COMMON block we are trying to add has a blank - name (i.e. "#BLNK_COM") then we set it to __BLANK - because the darn "#" character makes GDB's input - parser have fits. */ +/* Special expression printing for Fortran. */ +static void +print_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec) +{ + int pc = *pos; + enum exp_opcode op = exp->elts[pc].opcode; - if (strcmp (name, BLANK_COMMON_NAME_ORIGINAL) == 0 - || strcmp (name, BLANK_COMMON_NAME_MF77) == 0) + switch (op) { + default: + print_subexp_standard (exp, pos, stream, prec); + return; - xfree (name); - name = alloca (strlen (BLANK_COMMON_NAME_LOCAL) + 1); - strcpy (name, BLANK_COMMON_NAME_LOCAL); - } - - tmp = allocate_saved_f77_common_node (); - - local_copy_func_stab = xmalloc (strlen (func_stab) + 1); - strcpy (local_copy_func_stab, func_stab); - - tmp->name = xmalloc (strlen (name) + 1); - - /* local_copy_func_stab is a stabstring, let us first extract the - function name from the stab by NULLing out the ':' character. */ - - - c = NULL; - c = strchr (local_copy_func_stab, ':'); - - if (c) - *c = '\0'; - else - error (_("Malformed function STAB found in add_common_block()")); - - - tmp->owning_function = xmalloc (strlen (local_copy_func_stab) + 1); + case UNOP_FORTRAN_KIND: + print_unop_subexp_f (exp, pos, stream, prec, "KIND"); + return; - strcpy (tmp->owning_function, local_copy_func_stab); + case UNOP_FORTRAN_FLOOR: + print_unop_subexp_f (exp, pos, stream, prec, "FLOOR"); + return; - strcpy (tmp->name, name); - tmp->offset = offset; - tmp->next = NULL; - tmp->entries = NULL; - tmp->secnum = secnum; + case UNOP_FORTRAN_CEILING: + print_unop_subexp_f (exp, pos, stream, prec, "CEILING"); + return; - current_common = tmp; + case BINOP_FORTRAN_CMPLX: + print_binop_subexp_f (exp, pos, stream, prec, "CMPLX"); + return; - if (head_common_list == NULL) - { - head_common_list = tail_common_list = tmp; - } - else - { - tail_common_list->next = tmp; - tail_common_list = tmp; + case BINOP_FORTRAN_MODULO: + print_binop_subexp_f (exp, pos, stream, prec, "MODULO"); + return; } } -#endif -/* The following function simply enters a given common entry onto - the "current_common" block that has been saved away. */ +/* Special expression names for Fortran. */ -#if 0 -static void -add_common_entry (struct symbol *entry_sym_ptr) +static const char * +op_name_f (enum exp_opcode opcode) { - COMMON_ENTRY_PTR tmp; - - - - /* The order of this list is important, since - we expect the entries to appear in decl. - order when we later issue "info common" calls */ - - tmp = allocate_common_entry_node (); - - tmp->next = NULL; - tmp->symbol = entry_sym_ptr; - - if (current_common == NULL) - error (_("Attempt to add COMMON entry with no block open!")); - else + switch (opcode) { - if (current_common->entries == NULL) - { - current_common->entries = tmp; - current_common->end_of_entries = tmp; - } - else - { - current_common->end_of_entries->next = tmp; - current_common->end_of_entries = tmp; - } + default: + return op_name_standard (opcode); + +#define OP(name) \ + case name: \ + return #name ; +#include "fortran-operator.def" +#undef OP } } -#endif -/* This routine finds the first encountred COMMON block named "name" */ +/* Special expression dumping for Fortran. */ -#if 0 -static SAVED_F77_COMMON_PTR -find_first_common_named (char *name) +static int +dump_subexp_body_f (struct expression *exp, + struct ui_file *stream, int elt) { + int opcode = exp->elts[elt].opcode; + int oplen, nargs, i; - SAVED_F77_COMMON_PTR tmp; - - tmp = head_common_list; - - while (tmp != NULL) + switch (opcode) { - if (strcmp (tmp->name, name) == 0) - return (tmp); - else - tmp = tmp->next; + default: + return dump_subexp_body_standard (exp, stream, elt); + + case UNOP_FORTRAN_KIND: + case UNOP_FORTRAN_FLOOR: + case UNOP_FORTRAN_CEILING: + case BINOP_FORTRAN_CMPLX: + case BINOP_FORTRAN_MODULO: + operator_length_f (exp, (elt + 1), &oplen, &nargs); + break; } - return (NULL); -} -#endif -/* This routine finds the first encountred COMMON block named "name" - that belongs to function funcname */ + elt += oplen; + for (i = 0; i < nargs; i += 1) + elt = dump_subexp (exp, stream, elt); -SAVED_F77_COMMON_PTR -find_common_for_function (char *name, char *funcname) -{ + return elt; +} - SAVED_F77_COMMON_PTR tmp; +/* Special expression checking for Fortran. */ - tmp = head_common_list; +static int +operator_check_f (struct expression *exp, int pos, + int (*objfile_func) (struct objfile *objfile, + void *data), + void *data) +{ + const union exp_element *const elts = exp->elts; - while (tmp != NULL) + switch (elts[pos].opcode) { - if (strcmp (tmp->name, name) == 0 - && strcmp (tmp->owning_function, funcname) == 0) - return (tmp); - else - tmp = tmp->next; + case UNOP_FORTRAN_KIND: + case UNOP_FORTRAN_FLOOR: + case UNOP_FORTRAN_CEILING: + case BINOP_FORTRAN_CMPLX: + case BINOP_FORTRAN_MODULO: + /* Any references to objfiles are held in the arguments to this + expression, not within the expression itself, so no additional + checking is required here, the outer expression iteration code + will take care of checking each argument. */ + break; + + default: + return operator_check_standard (exp, pos, objfile_func, data); } - return (NULL); + + return 0; } +static const char *f_extensions[] = +{ + ".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP", + ".f90", ".F90", ".f95", ".F95", ".f03", ".F03", ".f08", ".F08", + NULL +}; -#if 0 +/* Expression processing for Fortran. */ +static const struct exp_descriptor exp_descriptor_f = +{ + print_subexp_f, + operator_length_f, + operator_check_f, + op_name_f, + dump_subexp_body_f, + evaluate_subexp_f +}; -/* The following function is called to patch up the offsets - for the statics contained in the COMMON block named - "name." */ +/* Constant data that describes the Fortran language. */ -static void -patch_common_entries (SAVED_F77_COMMON_PTR blk, CORE_ADDR offset, int secnum) +extern const struct language_data f_language_data = { - COMMON_ENTRY_PTR entry; + "fortran", + "Fortran", + language_fortran, + range_check_on, + case_sensitive_off, + array_column_major, + macro_expansion_no, + f_extensions, + &exp_descriptor_f, + f_parse, /* parser */ + null_post_parser, + f_printchar, /* Print character constant */ + f_printstr, /* function to print string constant */ + f_emit_char, /* Function to print a single character */ + f_print_typedef, /* Print a typedef using appropriate syntax */ + f_value_print_innner, /* la_value_print_inner */ + c_value_print, /* FIXME */ + NULL, /* name_of_this */ + false, /* la_store_sym_names_in_linkage_form_p */ + cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ + NULL, /* Language specific + class_name_from_physname */ + f_op_print_tab, /* expression operators for printing */ + 0, /* arrays are first-class (not c-style) */ + 1, /* String lower bound */ + f_word_break_characters, + f_collect_symbol_completion_matches, + c_watch_location_expression, + cp_get_symbol_name_matcher, /* la_get_symbol_name_matcher */ + &default_varobj_ops, + NULL, + f_is_string_type_p, + "(...)" /* la_struct_too_deep_ellipsis */ +}; + +/* Class representing the Fortran language. */ - blk->offset = offset; /* Keep this around for future use. */ +class f_language : public language_defn +{ +public: + f_language () + : language_defn (language_fortran, f_language_data) + { /* Nothing. */ } + + /* See language.h. */ + void language_arch_info (struct gdbarch *gdbarch, + struct language_arch_info *lai) const override + { + const struct builtin_f_type *builtin = builtin_f_type (gdbarch); + + lai->string_char_type = builtin->builtin_character; + lai->primitive_type_vector + = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_f_primitive_types + 1, + struct type *); + + lai->primitive_type_vector [f_primitive_type_character] + = builtin->builtin_character; + lai->primitive_type_vector [f_primitive_type_logical] + = builtin->builtin_logical; + lai->primitive_type_vector [f_primitive_type_logical_s1] + = builtin->builtin_logical_s1; + lai->primitive_type_vector [f_primitive_type_logical_s2] + = builtin->builtin_logical_s2; + lai->primitive_type_vector [f_primitive_type_logical_s8] + = builtin->builtin_logical_s8; + lai->primitive_type_vector [f_primitive_type_real] + = builtin->builtin_real; + lai->primitive_type_vector [f_primitive_type_real_s8] + = builtin->builtin_real_s8; + lai->primitive_type_vector [f_primitive_type_real_s16] + = builtin->builtin_real_s16; + lai->primitive_type_vector [f_primitive_type_complex_s8] + = builtin->builtin_complex_s8; + lai->primitive_type_vector [f_primitive_type_complex_s16] + = builtin->builtin_complex_s16; + lai->primitive_type_vector [f_primitive_type_void] + = builtin->builtin_void; + + lai->bool_type_symbol = "logical"; + lai->bool_type_default = builtin->builtin_logical_s2; + } + + /* See language.h. */ + unsigned int search_name_hash (const char *name) const override + { + return cp_search_name_hash (name); + } - entry = blk->entries; + /* See language.h. */ - while (entry != NULL) - { - SYMBOL_VALUE (entry->symbol) += offset; - SYMBOL_SECTION (entry->symbol) = secnum; + char *demangle (const char *mangled, int options) const override + { + /* We could support demangling here to provide module namespaces + also for inferiors with only minimal symbol table (ELF symbols). + Just the mangling standard is not standardized across compilers + and there is no DW_AT_producer available for inferiors with only + the ELF symbols to check the mangling kind. */ + return nullptr; + } + + /* See language.h. */ + + void print_type (struct type *type, const char *varstring, + struct ui_file *stream, int show, int level, + const struct type_print_options *flags) const override + { + f_print_type (type, varstring, stream, show, level, flags); + } +}; - entry = entry->next; - } - blk->secnum = secnum; -} +/* Single instance of the Fortran language class. */ -/* Patch all commons named "name" that need patching.Since COMMON - blocks occur with relative infrequency, we simply do a linear scan on - the name. Eventually, the best way to do this will be a - hashed-lookup. Secnum is the section number for the .bss section - (which is where common data lives). */ +static f_language f_language_defn; -static void -patch_all_commons_by_name (char *name, CORE_ADDR offset, int secnum) +static void * +build_fortran_types (struct gdbarch *gdbarch) { + struct builtin_f_type *builtin_f_type + = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_f_type); - SAVED_F77_COMMON_PTR tmp; + builtin_f_type->builtin_void + = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void"); - /* For blank common blocks, change the canonical reprsentation - of a blank name */ + builtin_f_type->builtin_character + = arch_type (gdbarch, TYPE_CODE_CHAR, TARGET_CHAR_BIT, "character"); - if (strcmp (name, BLANK_COMMON_NAME_ORIGINAL) == 0 - || strcmp (name, BLANK_COMMON_NAME_MF77) == 0) - { - xfree (name); - name = alloca (strlen (BLANK_COMMON_NAME_LOCAL) + 1); - strcpy (name, BLANK_COMMON_NAME_LOCAL); - } + builtin_f_type->builtin_logical_s1 + = arch_boolean_type (gdbarch, TARGET_CHAR_BIT, 1, "logical*1"); - tmp = head_common_list; + builtin_f_type->builtin_integer_s2 + = arch_integer_type (gdbarch, gdbarch_short_bit (gdbarch), 0, + "integer*2"); - while (tmp != NULL) - { - if (COMMON_NEEDS_PATCHING (tmp)) - if (strcmp (tmp->name, name) == 0) - patch_common_entries (tmp, offset, secnum); + builtin_f_type->builtin_integer_s8 + = arch_integer_type (gdbarch, gdbarch_long_long_bit (gdbarch), 0, + "integer*8"); - tmp = tmp->next; - } -} -#endif - -/* This macro adds the symbol-number for the start of the function - (the symbol number of the .bf) referenced by symnum_fcn to a - list. This list, in reality should be a FIFO queue but since - #line pragmas sometimes cause line ranges to get messed up - we simply create a linear list. This list can then be searched - first by a queueing algorithm and upon failure fall back to - a linear scan. */ - -#if 0 -#define ADD_BF_SYMNUM(bf_sym,fcn_sym) \ - \ - if (saved_bf_list == NULL) \ -{ \ - tmp_bf_ptr = allocate_saved_bf_node(); \ - \ - tmp_bf_ptr->symnum_bf = (bf_sym); \ - tmp_bf_ptr->symnum_fcn = (fcn_sym); \ - tmp_bf_ptr->next = NULL; \ - \ - current_head_bf_list = saved_bf_list = tmp_bf_ptr; \ - saved_bf_list_end = tmp_bf_ptr; \ - } \ -else \ -{ \ - tmp_bf_ptr = allocate_saved_bf_node(); \ - \ - tmp_bf_ptr->symnum_bf = (bf_sym); \ - tmp_bf_ptr->symnum_fcn = (fcn_sym); \ - tmp_bf_ptr->next = NULL; \ - \ - saved_bf_list_end->next = tmp_bf_ptr; \ - saved_bf_list_end = tmp_bf_ptr; \ - } -#endif - -/* This function frees the entire (.bf,function) list */ - -#if 0 -static void -clear_bf_list (void) -{ + builtin_f_type->builtin_logical_s2 + = arch_boolean_type (gdbarch, gdbarch_short_bit (gdbarch), 1, + "logical*2"); - SAVED_BF_PTR tmp = saved_bf_list; - SAVED_BF_PTR next = NULL; + builtin_f_type->builtin_logical_s8 + = arch_boolean_type (gdbarch, gdbarch_long_long_bit (gdbarch), 1, + "logical*8"); - while (tmp != NULL) - { - next = tmp->next; - xfree (tmp); - tmp = next; - } - saved_bf_list = NULL; -} -#endif + builtin_f_type->builtin_integer + = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 0, + "integer"); -int global_remote_debug; + builtin_f_type->builtin_logical + = arch_boolean_type (gdbarch, gdbarch_int_bit (gdbarch), 1, + "logical*4"); -#if 0 + builtin_f_type->builtin_real + = arch_float_type (gdbarch, gdbarch_float_bit (gdbarch), + "real", gdbarch_float_format (gdbarch)); + builtin_f_type->builtin_real_s8 + = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch), + "real*8", gdbarch_double_format (gdbarch)); + auto fmt = gdbarch_floatformat_for_type (gdbarch, "real(kind=16)", 128); + if (fmt != nullptr) + builtin_f_type->builtin_real_s16 + = arch_float_type (gdbarch, 128, "real*16", fmt); + else if (gdbarch_long_double_bit (gdbarch) == 128) + builtin_f_type->builtin_real_s16 + = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch), + "real*16", gdbarch_long_double_format (gdbarch)); + else + builtin_f_type->builtin_real_s16 + = arch_type (gdbarch, TYPE_CODE_ERROR, 128, "real*16"); -static long -get_bf_for_fcn (long the_function) -{ - SAVED_BF_PTR tmp; - int nprobes = 0; + builtin_f_type->builtin_complex_s8 + = init_complex_type ("complex*8", builtin_f_type->builtin_real); + builtin_f_type->builtin_complex_s16 + = init_complex_type ("complex*16", builtin_f_type->builtin_real_s8); - /* First use a simple queuing algorithm (i.e. look and see if the - item at the head of the queue is the one you want) */ + if (builtin_f_type->builtin_real_s16->code () == TYPE_CODE_ERROR) + builtin_f_type->builtin_complex_s32 + = arch_type (gdbarch, TYPE_CODE_ERROR, 256, "complex*32"); + else + builtin_f_type->builtin_complex_s32 + = init_complex_type ("complex*32", builtin_f_type->builtin_real_s16); - if (saved_bf_list == NULL) - internal_error (__FILE__, __LINE__, - _("cannot get .bf node off empty list")); + return builtin_f_type; +} - if (current_head_bf_list != NULL) - if (current_head_bf_list->symnum_fcn == the_function) - { - if (global_remote_debug) - fprintf_unfiltered (gdb_stderr, "*"); +static struct gdbarch_data *f_type_data; - tmp = current_head_bf_list; - current_head_bf_list = current_head_bf_list->next; - return (tmp->symnum_bf); - } +const struct builtin_f_type * +builtin_f_type (struct gdbarch *gdbarch) +{ + return (const struct builtin_f_type *) gdbarch_data (gdbarch, f_type_data); +} - /* If the above did not work (probably because #line directives were - used in the sourcefile and they messed up our internal tables) we now do - the ugly linear scan */ +void _initialize_f_language (); +void +_initialize_f_language () +{ + f_type_data = gdbarch_data_register_post_init (build_fortran_types); +} - if (global_remote_debug) - fprintf_unfiltered (gdb_stderr, "\ndefaulting to linear scan\n"); +/* See f-lang.h. */ - nprobes = 0; - tmp = saved_bf_list; - while (tmp != NULL) +struct value * +fortran_argument_convert (struct value *value, bool is_artificial) +{ + if (!is_artificial) { - nprobes++; - if (tmp->symnum_fcn == the_function) + /* If the value is not in the inferior e.g. registers values, + convenience variables and user input. */ + if (VALUE_LVAL (value) != lval_memory) { - if (global_remote_debug) - fprintf_unfiltered (gdb_stderr, "Found in %d probes\n", nprobes); - current_head_bf_list = tmp->next; - return (tmp->symnum_bf); + struct type *type = value_type (value); + const int length = TYPE_LENGTH (type); + const CORE_ADDR addr + = value_as_long (value_allocate_space_in_inferior (length)); + write_memory (addr, value_contents (value), length); + struct value *val + = value_from_contents_and_address (type, value_contents (value), + addr); + return value_addr (val); } - tmp = tmp->next; + else + return value_addr (value); /* Program variables, e.g. arrays. */ } - - return (-1); + return value; } -static SAVED_FUNCTION_PTR saved_function_list = NULL; -static SAVED_FUNCTION_PTR saved_function_list_end = NULL; +/* See f-lang.h. */ -static void -clear_function_list (void) +struct type * +fortran_preserve_arg_pointer (struct value *arg, struct type *type) { - SAVED_FUNCTION_PTR tmp = saved_function_list; - SAVED_FUNCTION_PTR next = NULL; - - while (tmp != NULL) - { - next = tmp->next; - xfree (tmp); - tmp = next; - } - - saved_function_list = NULL; + if (value_type (arg)->code () == TYPE_CODE_PTR) + return value_type (arg); + return type; } -#endif