X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ff-lang.c;h=c7c47cf8dcfeebadb91f76b4a68a1331f531d093;hb=ddf5db90a175756b3a5c39ee87d549d9f9d09d28;hp=6b49beb2b1f1ca1c13017830f90e64f9908a1745;hpb=6ccb916229b6180c23485cc27d06acd1715efbdd;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 6b49beb2b1..c7c47cf8dc 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 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,56 +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. */ +/* Local functions */ -struct saved_fcn - { - long line_offset; /* Line offset for function */ - struct saved_fcn *next; - }; +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 the encoding that should be used for the character type + TYPE. */ -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; - }; +static const char * +f_get_encoding (struct type *type) +{ + const char *encoding; -typedef struct saved_fcn SAVED_FUNCTION, *SAVED_FUNCTION_PTR; -typedef struct saved_bf_symnum SAVED_BF, *SAVED_BF_PTR; + 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; -/* Local functions */ + default: + error (_("unrecognized character type")); + } -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 - -static void f_printchar (int c, struct ui_file * stream); -static void f_emit_char (int c, 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 @@ -80,56 +79,20 @@ static void f_emit_char (int c, struct ui_file * stream, int quoter); be replaced with a true F77 version. */ static void -f_emit_char (int c, struct ui_file *stream, int quoter) +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 ui_file *stream) +f_printchar (int c, struct type *type, struct ui_file *stream) { fputs_filtered ("'", stream); - LA_EMIT_CHAR (c, stream, '\''); + LA_EMIT_CHAR (c, type, stream, '\''); fputs_filtered ("'", stream); } @@ -138,89 +101,23 @@ f_printchar (int c, 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, const gdb_byte *string, - unsigned int length, int width, int force_ellipses) +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; + const char *type_encoding = f_get_encoding (type); - if (length == 0) - { - fputs_filtered ("''", gdb_stdout); - return; - } - - for (i = 0; i < length && things_printed < 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; - - QUIT; - - 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 > repeat_count_threshold) - { - if (in_quotes) - { - if (inspect_it) - fputs_filtered ("\\', ", stream); - else - fputs_filtered ("', ", stream); - in_quotes = 0; - } - f_printchar (string[i], stream); - fprintf_filtered (stream, " ", reps); - i = rep1 - 1; - things_printed += repeat_count_threshold; - need_comma = 1; - } - else - { - if (!in_quotes) - { - if (inspect_it) - fputs_filtered ("\\'", stream); - else - fputs_filtered ("'", stream); - in_quotes = 1; - } - LA_EMIT_CHAR (string[i], stream, '"'); - ++things_printed; - } - } + if (TYPE_LENGTH (type) == 4) + fputs_filtered ("4_", stream); - /* Terminate the quotes if necessary. */ - if (in_quotes) - { - if (inspect_it) - fputs_filtered ("\\'", stream); - else - fputs_filtered ("'", stream); - } + if (!encoding || !*encoding) + encoding = type_encoding; - if (force_ellipses || i < length) - fputs_filtered ("...", stream); + generic_printstr (stream, type, string, length, encoding, + force_ellipses, '\'', 0, options); } @@ -248,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 { @@ -256,6 +153,7 @@ enum f_primitive_types { f_primitive_type_logical, f_primitive_type_logical_s1, f_primitive_type_logical_s2, + f_primitive_type_logical_s8, f_primitive_type_integer, f_primitive_type_integer_s2, f_primitive_type_real, @@ -286,6 +184,8 @@ f_language_arch_info (struct gdbarch *gdbarch, = 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] @@ -298,540 +198,608 @@ f_language_arch_info (struct gdbarch *gdbarch, = 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; } -/* 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 *, int, - enum val_prettyprint); +/* Remove the modules separator :: from the default break list. */ -const struct language_defn f_language_defn = +static const char * +f_word_break_characters (void) { - "fortran", - language_fortran, - range_check_on, - type_check_on, - case_sensitive_off, - array_column_major, - &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 */ - f_val_print, /* Print a value using appropriate syntax */ - c_value_print, /* FIXME */ - NULL, /* Language specific skip_trampoline */ - value_of_this, /* value_of_this */ - basic_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 */ - default_word_break_characters, - f_language_arch_info, - default_print_array_index, - default_pass_by_reference, - LANG_MAGIC -}; + static char *retval; -static void * -build_fortran_types (struct gdbarch *gdbarch) -{ - struct builtin_f_type *builtin_f_type - = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_f_type); + if (!retval) + { + char *s; - builtin_f_type->builtin_void = - init_type (TYPE_CODE_VOID, 1, - 0, - "VOID", (struct objfile *) NULL); - - builtin_f_type->builtin_character = - init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - 0, - "character", (struct objfile *) NULL); - - builtin_f_type->builtin_logical_s1 = - init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, - "logical*1", (struct objfile *) NULL); - - builtin_f_type->builtin_integer_s2 = - init_type (TYPE_CODE_INT, - gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, - 0, "integer*2", (struct objfile *) NULL); - - builtin_f_type->builtin_logical_s2 = - init_type (TYPE_CODE_BOOL, - gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, "logical*2", (struct objfile *) NULL); - - builtin_f_type->builtin_integer = - init_type (TYPE_CODE_INT, - gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, - 0, "integer", (struct objfile *) NULL); - - builtin_f_type->builtin_logical = - init_type (TYPE_CODE_BOOL, - gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, - TYPE_FLAG_UNSIGNED, "logical*4", (struct objfile *) NULL); - - builtin_f_type->builtin_real = - init_type (TYPE_CODE_FLT, - gdbarch_float_bit (gdbarch) / TARGET_CHAR_BIT, - 0, - "real", (struct objfile *) NULL); - - builtin_f_type->builtin_real_s8 = - init_type (TYPE_CODE_FLT, - gdbarch_double_bit (gdbarch) / TARGET_CHAR_BIT, - 0, - "real*8", (struct objfile *) NULL); - - builtin_f_type->builtin_real_s16 = - init_type (TYPE_CODE_FLT, - gdbarch_long_double_bit (gdbarch) / TARGET_CHAR_BIT, - 0, - "real*16", (struct objfile *) NULL); - - builtin_f_type->builtin_complex_s8 = - init_type (TYPE_CODE_COMPLEX, - 2 * gdbarch_float_bit (gdbarch) / TARGET_CHAR_BIT, - 0, - "complex*8", (struct objfile *) NULL); - TYPE_TARGET_TYPE (builtin_f_type->builtin_complex_s8) - = builtin_f_type->builtin_real; - - builtin_f_type->builtin_complex_s16 = - init_type (TYPE_CODE_COMPLEX, - 2 * gdbarch_double_bit (gdbarch) / TARGET_CHAR_BIT, - 0, - "complex*16", (struct objfile *) NULL); - TYPE_TARGET_TYPE (builtin_f_type->builtin_complex_s16) - = builtin_f_type->builtin_real_s8; - - /* We have a new size == 4 double floats for the - complex*32 data type */ - - builtin_f_type->builtin_complex_s32 = - init_type (TYPE_CODE_COMPLEX, - 2 * gdbarch_long_double_bit (gdbarch) / TARGET_CHAR_BIT, - 0, - "complex*32", (struct objfile *) NULL); - TYPE_TARGET_TYPE (builtin_f_type->builtin_complex_s32) - = builtin_f_type->builtin_real_s16; + retval = xstrdup (default_word_break_characters ()); + s = strchr (retval, ':'); + if (s) + { + char *last_char = &s[strlen (s) - 1]; - return builtin_f_type; + *s = *last_char; + *last_char = 0; + } + } + return retval; } -static struct gdbarch_data *f_type_data; +/* Consider the modules separator :: as a valid symbol name character + class. */ -const struct builtin_f_type * -builtin_f_type (struct gdbarch *gdbarch) +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 gdbarch_data (gdbarch, f_type_data); + default_collect_symbol_completion_matches_break_on (tracker, mode, + compare_name, + text, word, ":", code); } -void -_initialize_f_language (void) -{ - f_type_data = gdbarch_data_register_post_init (build_fortran_types); - - add_language (&f_language_defn); -} +/* Special expression evaluation cases for Fortran. */ -#if 0 -static SAVED_BF_PTR -allocate_saved_bf_node (void) +static struct value * +evaluate_subexp_f (struct type *expect_type, struct expression *exp, + int *pos, enum noside noside) { - SAVED_BF_PTR new; + struct value *arg1 = NULL, *arg2 = NULL; + enum exp_opcode op; + int pc; + struct type *type; - new = (SAVED_BF_PTR) xmalloc (sizeof (SAVED_BF)); - return (new); -} + pc = *pos; + *pos += 1; + op = exp->elts[pc].opcode; -static SAVED_FUNCTION * -allocate_saved_function_node (void) -{ - SAVED_FUNCTION *new; + 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 (type)) + { + 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 (type) != TYPE_CODE (value_type (arg2))) + error (_("non-matching types for parameters to MOD ()")); + switch (TYPE_CODE (type)) + { + 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)); - new = (SAVED_FUNCTION *) xmalloc (sizeof (SAVED_FUNCTION)); - return (new); -} + 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) != 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); + } -static SAVED_F77_COMMON_PTR -allocate_saved_f77_common_node (void) -{ - SAVED_F77_COMMON_PTR new; + 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) != 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); + } - new = (SAVED_F77_COMMON_PTR) xmalloc (sizeof (SAVED_F77_COMMON)); - return (new); -} + 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 (type) != TYPE_CODE (value_type (arg2))) + error (_("non-matching types for parameters to MODULO ()")); + /* MODULO(A, P) = A - FLOOR (A / P) * P */ + switch (TYPE_CODE (type)) + { + 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)); + } -static COMMON_ENTRY_PTR -allocate_common_entry_node (void) -{ - COMMON_ENTRY_PTR new; + 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 (type)) + { + 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))); + } - new = (COMMON_ENTRY_PTR) xmalloc (sizeof (COMMON_ENTRY)); - return (new); + /* Should be unreachable. */ + return nullptr; } -#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 - */ +/* Return true if TYPE is a string. */ -static SAVED_BF_PTR tmp_bf_ptr; /* Generic temporary for use - in macros */ +static bool +f_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + return (TYPE_CODE (type) == TYPE_CODE_STRING + || (TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CHAR)); +} -/* The following function simply enters a given common block onto - the global common block chain */ +/* Special expression lengths for Fortran. */ static void -add_common_block (char *name, CORE_ADDR offset, int secnum, char *func_stab) +operator_length_f (const struct expression *exp, int pc, int *oplenp, + int *argsp) { - SAVED_F77_COMMON_PTR tmp; - char *c, *local_copy_func_stab; - - /* 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. */ - + int oplen = 1; + int args = 0; - if (strcmp (name, BLANK_COMMON_NAME_ORIGINAL) == 0 - || strcmp (name, BLANK_COMMON_NAME_MF77) == 0) + switch (exp->elts[pc - 1].opcode) { + default: + operator_length_standard (exp, pc, oplenp, argsp); + return; - xfree (name); - name = alloca (strlen (BLANK_COMMON_NAME_LOCAL) + 1); - strcpy (name, BLANK_COMMON_NAME_LOCAL); + 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; } - 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); + *oplenp = oplen; + *argsp = args; +} - strcpy (tmp->owning_function, local_copy_func_stab); +/* 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. */ - strcpy (tmp->name, name); - tmp->offset = offset; - tmp->next = NULL; - tmp->entries = NULL; - tmp->secnum = secnum; +static void +print_unop_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec, + const char *name) +{ + (*pos)++; + fprintf_filtered (stream, "%s(", name); + print_subexp (exp, pos, stream, PREC_SUFFIX); + fputs_filtered (")", stream); +} - current_common = tmp; +/* 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. */ - if (head_common_list == NULL) - { - head_common_list = tail_common_list = tmp; - } - else - { - tail_common_list->next = tmp; - tail_common_list = tmp; - } +static void +print_binop_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec, + const char *name) +{ + (*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); } -#endif -/* The following function simply enters a given common entry onto - the "current_common" block that has been saved away. */ +/* Special expression printing for Fortran. */ -#if 0 static void -add_common_entry (struct symbol *entry_sym_ptr) +print_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec) { - COMMON_ENTRY_PTR tmp; + int pc = *pos; + enum exp_opcode op = exp->elts[pc].opcode; + switch (op) + { + default: + print_subexp_standard (exp, pos, stream, prec); + return; + case UNOP_FORTRAN_KIND: + print_unop_subexp_f (exp, pos, stream, prec, "KIND"); + return; - /* The order of this list is important, since - we expect the entries to appear in decl. - order when we later issue "info common" calls */ + case UNOP_FORTRAN_FLOOR: + print_unop_subexp_f (exp, pos, stream, prec, "FLOOR"); + return; - tmp = allocate_common_entry_node (); + case UNOP_FORTRAN_CEILING: + print_unop_subexp_f (exp, pos, stream, prec, "CEILING"); + return; - tmp->next = NULL; - tmp->symbol = entry_sym_ptr; + case BINOP_FORTRAN_CMPLX: + print_binop_subexp_f (exp, pos, stream, prec, "CMPLX"); + return; - if (current_common == NULL) - error (_("Attempt to add COMMON entry with no block open!")); - else - { - 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; - } + case BINOP_FORTRAN_MODULO: + print_binop_subexp_f (exp, pos, stream, prec, "MODULO"); + return; } } -#endif -/* This routine finds the first encountred COMMON block named "name" */ +/* Special expression names for Fortran. */ -#if 0 -static SAVED_F77_COMMON_PTR -find_first_common_named (char *name) +static const char * +op_name_f (enum exp_opcode opcode) { - - 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 op_name_standard (opcode); + +#define OP(name) \ + case name: \ + return #name ; +#include "fortran-operator.def" +#undef OP } - return (NULL); } -#endif -/* This routine finds the first encountred COMMON block named "name" - that belongs to function funcname */ +/* Special expression dumping for Fortran. */ -SAVED_F77_COMMON_PTR -find_common_for_function (char *name, char *funcname) +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 (DEPRECATED_STREQ (tmp->name, name) - && DEPRECATED_STREQ (tmp->owning_function, funcname)) - 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); -} + elt += oplen; + for (i = 0; i < nargs; i += 1) + elt = dump_subexp (exp, stream, elt); -#if 0 + return elt; +} -/* The following function is called to patch up the offsets - for the statics contained in the COMMON block named - "name." */ +/* Special expression checking for Fortran. */ -static void -patch_common_entries (SAVED_F77_COMMON_PTR blk, CORE_ADDR offset, int secnum) +static int +operator_check_f (struct expression *exp, int pos, + int (*objfile_func) (struct objfile *objfile, + void *data), + void *data) { - COMMON_ENTRY_PTR entry; - - blk->offset = offset; /* Keep this around for future use. */ - - entry = blk->entries; + const union exp_element *const elts = exp->elts; - while (entry != NULL) + switch (elts[pos].opcode) { - SYMBOL_VALUE (entry->symbol) += offset; - SYMBOL_SECTION (entry->symbol) = secnum; - - entry = entry->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); } - blk->secnum = secnum; -} -/* 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). */ + return 0; +} -static void -patch_all_commons_by_name (char *name, CORE_ADDR offset, int secnum) +static const char *f_extensions[] = { + ".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP", + ".f90", ".F90", ".f95", ".F95", ".f03", ".F03", ".f08", ".F08", + NULL +}; - SAVED_F77_COMMON_PTR tmp; - - /* For blank common blocks, change the canonical reprsentation - of a blank name */ - - 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); - } +/* 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 +}; - tmp = head_common_list; +extern const struct language_defn f_language_defn = +{ + "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_type, /* Print a type using appropriate syntax */ + f_print_typedef, /* Print a typedef using appropriate syntax */ + f_val_print, /* Print a value using appropriate syntax */ + c_value_print, /* FIXME */ + default_read_var_value, /* la_read_var_value */ + NULL, /* Language specific skip_trampoline */ + NULL, /* name_of_this */ + false, /* la_store_sym_names_in_linkage_form_p */ + cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ + basic_lookup_transparent_type,/* lookup_transparent_type */ - while (tmp != NULL) - { - if (COMMON_NEEDS_PATCHING (tmp)) - if (strcmp (tmp->name, name) == 0) - patch_common_entries (tmp, offset, secnum); + /* 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. */ + NULL, /* Language specific symbol demangler */ + NULL, + 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, + f_language_arch_info, + default_print_array_index, + default_pass_by_reference, + c_watch_location_expression, + cp_get_symbol_name_matcher, /* la_get_symbol_name_matcher */ + iterate_over_symbols, + cp_search_name_hash, + &default_varobj_ops, + NULL, + NULL, + f_is_string_type_p, + "(...)" /* la_struct_too_deep_ellipsis */ +}; - 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) +static void * +build_fortran_types (struct gdbarch *gdbarch) { + struct builtin_f_type *builtin_f_type + = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_f_type); - SAVED_BF_PTR tmp = saved_bf_list; - SAVED_BF_PTR next = NULL; + builtin_f_type->builtin_void + = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void"); + + builtin_f_type->builtin_character + = arch_type (gdbarch, TYPE_CODE_CHAR, TARGET_CHAR_BIT, "character"); + + 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_integer_s8 + = arch_integer_type (gdbarch, gdbarch_long_long_bit (gdbarch), 0, + "integer*8"); + + 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"); + + builtin_f_type->builtin_integer + = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 0, + "integer"); + + builtin_f_type->builtin_logical + = arch_boolean_type (gdbarch, gdbarch_int_bit (gdbarch), 1, + "logical*4"); + + 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"); + + 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); - while (tmp != NULL) - { - next = tmp->next; - xfree (tmp); - tmp = next; - } - saved_bf_list = NULL; + return builtin_f_type; } -#endif -int global_remote_debug; - -#if 0 +static struct gdbarch_data *f_type_data; -static long -get_bf_for_fcn (long the_function) +const struct builtin_f_type * +builtin_f_type (struct gdbarch *gdbarch) { - SAVED_BF_PTR tmp; - int nprobes = 0; - - /* 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 (saved_bf_list == NULL) - internal_error (__FILE__, __LINE__, - _("cannot get .bf node off empty list")); - - if (current_head_bf_list != NULL) - if (current_head_bf_list->symnum_fcn == the_function) - { - if (global_remote_debug) - fprintf_unfiltered (gdb_stderr, "*"); - - tmp = current_head_bf_list; - current_head_bf_list = current_head_bf_list->next; - return (tmp->symnum_bf); - } + 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) +{ + 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 (TYPE_CODE (value_type (arg)) == TYPE_CODE_PTR) + return value_type (arg); + return type; } -#endif