Initial Fortran language support, adapted from work by Farooq Butt
(fmbutt@engage.sps.mot.com). * Makefile.in: Add Fortran-related files and dependencies. * defs.h (language_fortran): New language enum. * language.h (_LANG_fortran): Define. (MAX_FORTRAN_DIMS): Define. * expression.h: Reformat to standard. (MULTI_F77_SUBSCRIPT, OP_F77_UNDETERMINED_ARGLIST, OP_F77_LITERAL_COMPLEX, OP_F77_SUBSTR): New expression opcodes. * gdbtypes.h (TYPE_CODE_COMPLEX, TYPE_CODE_LITERAL_COMPLEX, TYPE_CODE_LITERAL_STRING): New type codes. (type): New fields upper_bound_type and lower_bound_type. (TYPE_ARRAY_UPPER_BOUND_TYPE, TYPE_ARRAY_LOWER_BOUND_TYPE, TYPE_ARRAY_UPPER_BOUND_VALUE, TYPE_ARRAY_LOWER_BOUND_VALUE): New macros. (builtin_type_f_character, etc): Declare. * value.h (VALUE_LITERAL_DATA, VALUE_SUBSTRING_START): Define. * f-exp.y: New file, Fortran expression grammar. * f-lang.c: New file, Fortran language support functions. * f-lang.h: New file, Fortran language support declarations. * f-typeprint.c: New file, Fortran type printing. * f-valprint.c: New file, Fortran value printing. * eval.c (evaluate_subexp): Add code for new expression opcodes, fix wording of error message. * gdbtypes.c (f77_create_literal_complex_type, f77_create_literal_string_type): New functions. * language.c (set_language_command): Add Fortran info. (calc_f77_array_dims): New function. * parse.c (length_of_subexp, prefixify_subexp): Add cases for new expression opcodes. * symfile.c (deduce_language_from_filename): Recognize .f and .F as Fortran source files. * valops.c (f77_value_literal_string, f77_value_substring, f77_value_literal_complex): New functions.
This commit is contained in:
parent
f3806e3b6c
commit
a91a61923d
13 changed files with 4209 additions and 118 deletions
|
@ -1,3 +1,40 @@
|
|||
Fri Aug 19 14:55:45 1994 Stan Shebs (shebs@andros.cygnus.com)
|
||||
|
||||
Initial Fortran language support, adapted from work by Farooq Butt
|
||||
(fmbutt@engage.sps.mot.com).
|
||||
* Makefile.in: Add Fortran-related files and dependencies.
|
||||
* defs.h (language_fortran): New language enum.
|
||||
* language.h (_LANG_fortran): Define.
|
||||
(MAX_FORTRAN_DIMS): Define.
|
||||
* expression.h: Reformat to standard.
|
||||
(MULTI_F77_SUBSCRIPT, OP_F77_UNDETERMINED_ARGLIST,
|
||||
OP_F77_LITERAL_COMPLEX, OP_F77_SUBSTR): New expression opcodes.
|
||||
* gdbtypes.h (TYPE_CODE_COMPLEX, TYPE_CODE_LITERAL_COMPLEX,
|
||||
TYPE_CODE_LITERAL_STRING): New type codes.
|
||||
(type): New fields upper_bound_type and lower_bound_type.
|
||||
(TYPE_ARRAY_UPPER_BOUND_TYPE, TYPE_ARRAY_LOWER_BOUND_TYPE,
|
||||
TYPE_ARRAY_UPPER_BOUND_VALUE, TYPE_ARRAY_LOWER_BOUND_VALUE): New
|
||||
macros.
|
||||
(builtin_type_f_character, etc): Declare.
|
||||
* value.h (VALUE_LITERAL_DATA, VALUE_SUBSTRING_START): Define.
|
||||
* f-exp.y: New file, Fortran expression grammar.
|
||||
* f-lang.c: New file, Fortran language support functions.
|
||||
* f-lang.h: New file, Fortran language support declarations.
|
||||
* f-typeprint.c: New file, Fortran type printing.
|
||||
* f-valprint.c: New file, Fortran value printing.
|
||||
* eval.c (evaluate_subexp): Add code for new expression opcodes,
|
||||
fix wording of error message.
|
||||
* gdbtypes.c (f77_create_literal_complex_type,
|
||||
f77_create_literal_string_type): New functions.
|
||||
* language.c (set_language_command): Add Fortran info.
|
||||
(calc_f77_array_dims): New function.
|
||||
* parse.c (length_of_subexp, prefixify_subexp): Add cases for new
|
||||
expression opcodes.
|
||||
* symfile.c (deduce_language_from_filename): Recognize .f and .F
|
||||
as Fortran source files.
|
||||
* valops.c (f77_value_literal_string, f77_value_substring,
|
||||
f77_value_literal_complex): New functions.
|
||||
|
||||
Fri Aug 19 13:35:01 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
|
||||
|
||||
* c-typeprint.c (c_print_type): Assume demangled arguments
|
||||
|
|
1246
gdb/f-exp.y
Normal file
1246
gdb/f-exp.y
Normal file
File diff suppressed because it is too large
Load diff
945
gdb/f-lang.c
Normal file
945
gdb/f-lang.c
Normal file
|
@ -0,0 +1,945 @@
|
|||
/* Fortran language support routines for GDB, the GNU debugger.
|
||||
Copyright 1993, 1994 Free Software Foundation, Inc.
|
||||
Contributed by Motorola. Adapted from the C parser 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "parser-defs.h"
|
||||
#include "language.h"
|
||||
#include "f-lang.h"
|
||||
|
||||
/* 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
|
||||
characters and strings is language specific.
|
||||
FIXME: This is a copy of the same function from c-exp.y. It should
|
||||
be replaced with a true F77 version. */
|
||||
|
||||
static void
|
||||
emit_char (c, stream, quoter)
|
||||
register int c;
|
||||
FILE *stream;
|
||||
int quoter;
|
||||
{
|
||||
c &= 0xFF; /* Avoid sign bit follies */
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: This is a copy of the same function from c-exp.y. It should
|
||||
be replaced with a true F77version. */
|
||||
|
||||
static void
|
||||
f_printchar (c, stream)
|
||||
int c;
|
||||
FILE *stream;
|
||||
{
|
||||
fputs_filtered ("'", stream);
|
||||
emit_char (c, stream, '\'');
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
/* Print the character string STRING, printing at most LENGTH characters.
|
||||
Printing stops early if the number hits print_max; repeat counts
|
||||
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. */
|
||||
|
||||
static void
|
||||
f_printstr (stream, string, length, force_ellipses)
|
||||
FILE *stream;
|
||||
char *string;
|
||||
unsigned int length;
|
||||
int force_ellipses;
|
||||
{
|
||||
register unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
extern int inspect_it;
|
||||
extern int repeat_count_threshold;
|
||||
extern int print_max;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("''", 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, " <repeats %u times>", 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;
|
||||
}
|
||||
emit_char (string[i], stream, '"');
|
||||
++things_printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\'", stream);
|
||||
else
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
if (force_ellipses || i < length)
|
||||
fputs_filtered ("...", stream);
|
||||
}
|
||||
|
||||
/* FIXME: This is a copy of c_create_fundamental_type(), before
|
||||
all the non-C types were stripped from it. Needs to be fixed
|
||||
by an experienced F77 programmer. */
|
||||
|
||||
static struct type *
|
||||
f_create_fundamental_type (objfile, typeid)
|
||||
struct objfile *objfile;
|
||||
int typeid;
|
||||
{
|
||||
register struct type *type = NULL;
|
||||
|
||||
switch (typeid)
|
||||
{
|
||||
case FT_VOID:
|
||||
type = init_type (TYPE_CODE_VOID,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "VOID", objfile);
|
||||
break;
|
||||
case FT_BOOLEAN:
|
||||
type = init_type (TYPE_CODE_BOOL,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "boolean", objfile);
|
||||
break;
|
||||
case FT_STRING:
|
||||
type = init_type (TYPE_CODE_STRING,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "string", objfile);
|
||||
break;
|
||||
case FT_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "character", objfile);
|
||||
break;
|
||||
case FT_SIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "integer*1", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_BOOL,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "logical*1", objfile);
|
||||
break;
|
||||
case FT_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0, "integer*2", objfile);
|
||||
break;
|
||||
case FT_SIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0, "short", objfile); /* FIXME-fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_BOOL,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "logical*2", objfile);
|
||||
break;
|
||||
case FT_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "integer*4", objfile);
|
||||
break;
|
||||
case FT_SIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "integer", objfile); /* FIXME -fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_BOOL,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "logical*4", objfile);
|
||||
break;
|
||||
case FT_FIXED_DECIMAL:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "fixed decimal", objfile);
|
||||
break;
|
||||
case FT_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long", objfile);
|
||||
break;
|
||||
case FT_SIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long", objfile); /* FIXME -fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
|
||||
break;
|
||||
case FT_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long long", objfile);
|
||||
break;
|
||||
case FT_SIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "signed long long", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "real", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "real*8", objfile);
|
||||
break;
|
||||
case FT_FLOAT_DECIMAL:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "floating decimal", objfile);
|
||||
break;
|
||||
case FT_EXT_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "real*16", objfile);
|
||||
break;
|
||||
case FT_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex*8", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex*16", objfile);
|
||||
break;
|
||||
case FT_EXT_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex*32", objfile);
|
||||
break;
|
||||
default:
|
||||
/* FIXME: For now, if we are asked to produce a type not in this
|
||||
language, create the equivalent of a C integer type with the
|
||||
name "<?type?>". When all the dust settles from the type
|
||||
reconstruction work, this should probably become an error. */
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "<?type?>", objfile);
|
||||
warning ("internal error: no F77 fundamental type %d", typeid);
|
||||
break;
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
|
||||
|
||||
/* Table of operators and their precedences for printing expressions. */
|
||||
|
||||
static const struct op_print f_op_print_tab[] = {
|
||||
{ "+", BINOP_ADD, PREC_ADD, 0 },
|
||||
{ "+", UNOP_PLUS, PREC_PREFIX, 0 },
|
||||
{ "-", BINOP_SUB, PREC_ADD, 0 },
|
||||
{ "-", UNOP_NEG, PREC_PREFIX, 0 },
|
||||
{ "*", BINOP_MUL, PREC_MUL, 0 },
|
||||
{ "/", BINOP_DIV, PREC_MUL, 0 },
|
||||
{ "DIV", BINOP_INTDIV, PREC_MUL, 0 },
|
||||
{ "MOD", BINOP_REM, PREC_MUL, 0 },
|
||||
{ "=", BINOP_ASSIGN, PREC_ASSIGN, 1 },
|
||||
{ ".OR.", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0 },
|
||||
{ ".AND.", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0 },
|
||||
{ ".NOT.", UNOP_LOGICAL_NOT, PREC_PREFIX, 0 },
|
||||
{ ".EQ.", BINOP_EQUAL, PREC_EQUAL, 0 },
|
||||
{ ".NE.", BINOP_NOTEQUAL, PREC_EQUAL, 0 },
|
||||
{ ".LE.", BINOP_LEQ, PREC_ORDER, 0 },
|
||||
{ ".GE.", BINOP_GEQ, PREC_ORDER, 0 },
|
||||
{ ".GT.", BINOP_GTR, PREC_ORDER, 0 },
|
||||
{ ".LT.", BINOP_LESS, PREC_ORDER, 0 },
|
||||
{ "**", UNOP_IND, PREC_PREFIX, 0 },
|
||||
{ "@", BINOP_REPEAT, PREC_REPEAT, 0 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* The built-in types of F77. */
|
||||
|
||||
struct type *builtin_type_f_character;
|
||||
struct type *builtin_type_f_integer;
|
||||
struct type *builtin_type_f_logical;
|
||||
struct type *builtin_type_f_logical_s1;
|
||||
struct type *builtin_type_f_logical_s2;
|
||||
struct type *builtin_type_f_integer;
|
||||
struct type *builtin_type_f_integer_s2;
|
||||
struct type *builtin_type_f_real;
|
||||
struct type *builtin_type_f_real_s8;
|
||||
struct type *builtin_type_f_real_s16;
|
||||
struct type *builtin_type_f_complex_s8;
|
||||
struct type *builtin_type_f_complex_s16;
|
||||
struct type *builtin_type_f_complex_s32;
|
||||
struct type *builtin_type_f_void;
|
||||
|
||||
struct type ** const (f_builtin_types[]) =
|
||||
{
|
||||
&builtin_type_f_character,
|
||||
&builtin_type_f_integer,
|
||||
&builtin_type_f_logical,
|
||||
&builtin_type_f_logical_s1,
|
||||
&builtin_type_f_logical_s2,
|
||||
&builtin_type_f_integer,
|
||||
&builtin_type_f_integer_s2,
|
||||
&builtin_type_f_real,
|
||||
&builtin_type_f_real_s8,
|
||||
&builtin_type_f_real_s16,
|
||||
&builtin_type_f_complex_s8,
|
||||
&builtin_type_f_complex_s16,
|
||||
#if 0
|
||||
&builtin_type_f_complex_s32,
|
||||
#endif
|
||||
&builtin_type_f_void,
|
||||
0
|
||||
};
|
||||
|
||||
int c_value_print();
|
||||
|
||||
const struct language_defn f_language_defn = {
|
||||
"fortran",
|
||||
language_fortran,
|
||||
f_builtin_types,
|
||||
range_check_on,
|
||||
type_check_on,
|
||||
f_parse, /* parser */
|
||||
f_error, /* parser error function */
|
||||
f_printchar, /* Print character constant */
|
||||
f_printstr, /* function to print string constant */
|
||||
f_create_fundamental_type, /* Create fundamental type in this language */
|
||||
f_print_type, /* Print a type using appropriate syntax */
|
||||
f_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* FIXME */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%o", "0", "o", ""}, /* Octal format info */
|
||||
{"%d", "", "d", ""}, /* Decimal format info */
|
||||
{"0x%x", "0x", "x", ""}, /* Hex format info */
|
||||
f_op_print_tab, /* expression operators for printing */
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_f_language ()
|
||||
{
|
||||
builtin_type_f_void =
|
||||
init_type (TYPE_CODE_VOID, 1,
|
||||
0,
|
||||
"VOID", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_character =
|
||||
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"character", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_logical_s1 =
|
||||
init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"logical*1", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_integer_s2 =
|
||||
init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"integer*2", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_logical_s2 =
|
||||
init_type (TYPE_CODE_BOOL, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"logical*2", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_integer =
|
||||
init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"integer", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_logical =
|
||||
init_type (TYPE_CODE_BOOL, TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"logical*4", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_real =
|
||||
init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"real", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_real_s8 =
|
||||
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"real*8", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_real_s16 =
|
||||
init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"real*16", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_complex_s8 =
|
||||
init_type (TYPE_CODE_COMPLEX, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"complex*8", (struct objfile *) NULL);
|
||||
|
||||
builtin_type_f_complex_s16 =
|
||||
init_type (TYPE_CODE_COMPLEX, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"complex*16", (struct objfile *) NULL);
|
||||
|
||||
#if 0
|
||||
/* We have a new size == 4 double floats for the
|
||||
complex*32 data type */
|
||||
|
||||
builtin_type_f_complex_s32 =
|
||||
init_type (TYPE_CODE_COMPLEX, TARGET_EXT_COMPLEX_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"complex*32", (struct objfile *) NULL);
|
||||
#endif
|
||||
builtin_type_string =
|
||||
init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"character string", (struct objfile *) NULL);
|
||||
|
||||
add_language (&f_language_defn);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
typedef struct saved_fcn SAVED_FUNCTION, *SAVED_FUNCTION_PTR;
|
||||
typedef struct saved_bf_symnum SAVED_BF, *SAVED_BF_PTR;
|
||||
|
||||
|
||||
SAVED_BF_PTR allocate_saved_bf_node()
|
||||
{
|
||||
SAVED_BF_PTR new;
|
||||
|
||||
new = (SAVED_BF_PTR) malloc (sizeof (SAVED_BF));
|
||||
|
||||
if (new == NULL)
|
||||
fatal("could not allocate enough memory to save one more .bf on save list");
|
||||
return(new);
|
||||
}
|
||||
|
||||
SAVED_FUNCTION *allocate_saved_function_node()
|
||||
{
|
||||
SAVED_FUNCTION *new;
|
||||
|
||||
new = (SAVED_FUNCTION *) malloc (sizeof (SAVED_FUNCTION));
|
||||
|
||||
if (new == NULL)
|
||||
fatal("could not allocate enough memory to save one more function on save list");
|
||||
|
||||
return(new);
|
||||
}
|
||||
|
||||
SAVED_F77_COMMON_PTR allocate_saved_f77_common_node()
|
||||
{
|
||||
SAVED_F77_COMMON_PTR new;
|
||||
|
||||
new = (SAVED_F77_COMMON_PTR) malloc (sizeof (SAVED_F77_COMMON));
|
||||
|
||||
if (new == NULL)
|
||||
fatal("could not allocate enough memory to save one more F77 COMMON blk on save list");
|
||||
|
||||
return(new);
|
||||
}
|
||||
|
||||
COMMON_ENTRY_PTR allocate_common_entry_node()
|
||||
{
|
||||
COMMON_ENTRY_PTR new;
|
||||
|
||||
new = (COMMON_ENTRY_PTR) malloc (sizeof (COMMON_ENTRY));
|
||||
|
||||
if (new == NULL)
|
||||
fatal("could not allocate enough memory to save one more COMMON entry on save list");
|
||||
|
||||
return(new);
|
||||
}
|
||||
|
||||
|
||||
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 */
|
||||
|
||||
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 */
|
||||
|
||||
void add_common_block(name,offset,secnum,func_stab)
|
||||
char *name;
|
||||
CORE_ADDR offset;
|
||||
int secnum;
|
||||
char *func_stab;
|
||||
|
||||
{
|
||||
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. */
|
||||
|
||||
|
||||
if (STREQ(name,BLANK_COMMON_NAME_ORIGINAL) ||
|
||||
STREQ(name,BLANK_COMMON_NAME_MF77))
|
||||
{
|
||||
|
||||
free(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 = malloc (strlen(func_stab) + 1);
|
||||
strcpy(local_copy_func_stab,func_stab);
|
||||
|
||||
tmp->name = malloc(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 = malloc (strlen(local_copy_func_stab) + 1);
|
||||
|
||||
strcpy(tmp->owning_function,local_copy_func_stab);
|
||||
|
||||
strcpy(tmp->name,name);
|
||||
tmp->offset = offset;
|
||||
tmp->next = NULL;
|
||||
tmp->entries = NULL;
|
||||
tmp->secnum = secnum;
|
||||
|
||||
current_common = tmp;
|
||||
|
||||
if (head_common_list == NULL)
|
||||
{
|
||||
head_common_list = tail_common_list = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail_common_list->next = tmp;
|
||||
tail_common_list = tmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* The following function simply enters a given common entry onto
|
||||
the "current_common" block that has been saved away. */
|
||||
|
||||
void add_common_entry(entry_sym_ptr)
|
||||
struct symbol *entry_sym_ptr;
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* This routine finds the first encountred COMMON block named "name" */
|
||||
|
||||
SAVED_F77_COMMON_PTR find_first_common_named(name)
|
||||
char *name;
|
||||
{
|
||||
|
||||
SAVED_F77_COMMON_PTR tmp;
|
||||
|
||||
tmp = head_common_list;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (STREQ(tmp->name,name))
|
||||
return(tmp);
|
||||
else
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* This routine finds the first encountred COMMON block named "name"
|
||||
that belongs to function funcname */
|
||||
|
||||
SAVED_F77_COMMON_PTR find_common_for_function(name, funcname)
|
||||
char *name;
|
||||
char *funcname;
|
||||
{
|
||||
|
||||
SAVED_F77_COMMON_PTR tmp;
|
||||
|
||||
tmp = head_common_list;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (STREQ(tmp->name,name) && STREQ(tmp->owning_function,funcname))
|
||||
return(tmp);
|
||||
else
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* The following function is called to patch up the offsets
|
||||
for the statics contained in the COMMON block named
|
||||
"name." */
|
||||
|
||||
|
||||
void patch_common_entries (blk, offset, secnum)
|
||||
SAVED_F77_COMMON_PTR blk;
|
||||
CORE_ADDR offset;
|
||||
int secnum;
|
||||
{
|
||||
COMMON_ENTRY_PTR entry;
|
||||
|
||||
blk->offset = offset; /* Keep this around for future use. */
|
||||
|
||||
entry = blk->entries;
|
||||
|
||||
while (entry != NULL)
|
||||
{
|
||||
SYMBOL_VALUE (entry->symbol) += offset;
|
||||
SYMBOL_SECTION (entry->symbol) = secnum;
|
||||
|
||||
entry = entry->next;
|
||||
}
|
||||
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). */
|
||||
|
||||
|
||||
void patch_all_commons_by_name (name, offset, secnum)
|
||||
char *name;
|
||||
CORE_ADDR offset;
|
||||
int secnum;
|
||||
{
|
||||
|
||||
SAVED_F77_COMMON_PTR tmp;
|
||||
|
||||
/* For blank common blocks, change the canonical reprsentation
|
||||
of a blank name */
|
||||
|
||||
if ((STREQ(name,BLANK_COMMON_NAME_ORIGINAL)) ||
|
||||
(STREQ(name,BLANK_COMMON_NAME_MF77)))
|
||||
{
|
||||
free(name);
|
||||
name = alloca(strlen(BLANK_COMMON_NAME_LOCAL) + 1);
|
||||
strcpy(name,BLANK_COMMON_NAME_LOCAL);
|
||||
}
|
||||
|
||||
tmp = head_common_list;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (COMMON_NEEDS_PATCHING(tmp))
|
||||
if (STREQ(tmp->name,name))
|
||||
patch_common_entries(tmp,offset,secnum);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#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; \
|
||||
}
|
||||
|
||||
|
||||
/* This function frees the entire (.bf,function) list */
|
||||
|
||||
void
|
||||
clear_bf_list()
|
||||
{
|
||||
|
||||
SAVED_BF_PTR tmp = saved_bf_list;
|
||||
SAVED_BF_PTR next = NULL;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
next = tmp->next;
|
||||
free(tmp);
|
||||
tmp=next;
|
||||
}
|
||||
saved_bf_list = NULL;
|
||||
}
|
||||
|
||||
int global_remote_debug;
|
||||
|
||||
long
|
||||
get_bf_for_fcn (the_function)
|
||||
long the_function;
|
||||
{
|
||||
SAVED_BF_PTR tmp;
|
||||
int nprobes = 0;
|
||||
long retval = 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)
|
||||
fatal ("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(stderr,"*");
|
||||
|
||||
tmp = current_head_bf_list;
|
||||
current_head_bf_list = current_head_bf_list->next;
|
||||
return(tmp->symnum_bf);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
if (global_remote_debug)
|
||||
fprintf(stderr,"\ndefaulting to linear scan\n");
|
||||
|
||||
nprobes = 0;
|
||||
tmp = saved_bf_list;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
nprobes++;
|
||||
if (tmp->symnum_fcn == the_function)
|
||||
{
|
||||
if (global_remote_debug)
|
||||
fprintf(stderr,"Found in %d probes\n",nprobes);
|
||||
current_head_bf_list = tmp->next;
|
||||
return(tmp->symnum_bf);
|
||||
}
|
||||
tmp= tmp->next;
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static SAVED_FUNCTION_PTR saved_function_list=NULL;
|
||||
static SAVED_FUNCTION_PTR saved_function_list_end=NULL;
|
||||
|
||||
void clear_function_list()
|
||||
{
|
||||
SAVED_FUNCTION_PTR tmp = saved_function_list;
|
||||
SAVED_FUNCTION_PTR next = NULL;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
next = tmp->next;
|
||||
free(tmp);
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
saved_function_list = NULL;
|
||||
}
|
90
gdb/f-lang.h
Normal file
90
gdb/f-lang.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* Fortran language support definitions for GDB, the GNU debugger.
|
||||
Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
Contributed by Motorola. Adapted from the C definitions 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
extern int f_parse PARAMS ((void));
|
||||
|
||||
extern void f_error PARAMS ((char *)); /* Defined in f-exp.y */
|
||||
|
||||
extern void f_print_type PARAMS ((struct type *, char *, FILE *, int, int));
|
||||
|
||||
extern int f_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *,
|
||||
int, int, int, enum val_prettyprint));
|
||||
|
||||
/* Language-specific data structures */
|
||||
|
||||
struct common_entry
|
||||
{
|
||||
struct symbol *symbol; /* The symbol node corresponding
|
||||
to this component */
|
||||
struct common_entry *next; /* The next component */
|
||||
};
|
||||
|
||||
struct saved_f77_common
|
||||
{
|
||||
char *name; /* Name of COMMON */
|
||||
char *owning_function; /* Name of parent function */
|
||||
int secnum; /* Section # of .bss */
|
||||
CORE_ADDR offset; /* Offset from .bss for
|
||||
this block */
|
||||
struct common_entry *entries; /* List of block's components */
|
||||
struct common_entry *end_of_entries; /* ptr. to end of components */
|
||||
struct saved_f77_common *next; /* Next saved COMMON block */
|
||||
};
|
||||
|
||||
typedef struct saved_f77_common SAVED_F77_COMMON, *SAVED_F77_COMMON_PTR;
|
||||
|
||||
typedef struct common_entry COMMON_ENTRY, *COMMON_ENTRY_PTR;
|
||||
|
||||
extern SAVED_F77_COMMON_PTR head_common_list; /* Ptr to 1st saved COMMON */
|
||||
extern SAVED_F77_COMMON_PTR tail_common_list; /* Ptr to last saved COMMON */
|
||||
extern SAVED_F77_COMMON_PTR current_common; /* Ptr to current COMMON */
|
||||
|
||||
#define UNINITIALIZED_SECNUM -1
|
||||
#define COMMON_NEEDS_PATCHING(blk) ((blk)->secnum == UNINITIALIZED_SECNUM)
|
||||
|
||||
#define BLANK_COMMON_NAME_ORIGINAL "#BLNK_COM" /* XLF assigned */
|
||||
#define BLANK_COMMON_NAME_MF77 "__BLNK__" /* MF77 assigned */
|
||||
#define BLANK_COMMON_NAME_LOCAL "__BLANK" /* Local GDB */
|
||||
|
||||
#define BOUND_FETCH_OK 1
|
||||
#define BOUND_FETCH_ERROR -999
|
||||
|
||||
/* When reasonable array bounds cannot be fetched, such as when
|
||||
you ask to 'mt print symbols' and there is no stack frame and
|
||||
therefore no way of knowing the bounds of stack-based arrays,
|
||||
we have to assign default bounds, these are as good as any... */
|
||||
|
||||
#define DEFAULT_UPPER_BOUND 999999
|
||||
#define DEFAULT_LOWER_BOUND -999999
|
||||
|
||||
extern char *real_main_name; /* Name of main function */
|
||||
extern int real_main_c_value; /* C_value field of main function */
|
||||
|
||||
extern int f77_get_dynamic_upperbound PARAMS ((struct type *, int *));
|
||||
|
||||
extern int f77_get_dynamic_lowerbound PARAMS ((struct type *, int *));
|
||||
|
||||
extern void f77_get_dynamic_array_length PARAMS ((struct type *));
|
||||
|
||||
#define DEFAULT_DOTMAIN_NAME_IN_MF77 ".MAIN_"
|
||||
#define DEFAULT_MAIN_NAME_IN_MF77 "MAIN_"
|
||||
#define DEFAULT_DOTMAIN_NAME_IN_XLF_BUGGY ".main "
|
||||
#define DEFAULT_DOTMAIN_NAME_IN_XLF ".main"
|
457
gdb/f-typeprint.c
Normal file
457
gdb/f-typeprint.c
Normal file
|
@ -0,0 +1,457 @@
|
|||
/* Support for printing Fortran types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "bfd.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "language.h"
|
||||
#include "demangle.h"
|
||||
#include "f-lang.h"
|
||||
#include "typeprint.h"
|
||||
#include "frame.h" /* ??? */
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void f_type_print_args PARAMS ((struct type *, FILE *));
|
||||
|
||||
static void f_type_print_varspec_suffix PARAMS ((struct type *, FILE *,
|
||||
int, int, int));
|
||||
|
||||
void f_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int));
|
||||
|
||||
void f_type_print_base PARAMS ((struct type *, FILE *, int, int));
|
||||
|
||||
|
||||
/* LEVEL is the depth to indent lines by. */
|
||||
|
||||
void
|
||||
f_print_type (type, varstring, stream, show, level)
|
||||
struct type *type;
|
||||
char *varstring;
|
||||
FILE *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
register enum type_code code;
|
||||
int demangled_args;
|
||||
|
||||
f_type_print_base (type, stream, show, level);
|
||||
code = TYPE_CODE (type);
|
||||
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 (type) == 0)
|
||||
&&
|
||||
(code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
|
||||
|| code == TYPE_CODE_METHOD
|
||||
|| code == TYPE_CODE_ARRAY
|
||||
|| code == TYPE_CODE_MEMBER
|
||||
|| code == TYPE_CODE_REF)))
|
||||
fputs_filtered (" ", stream);
|
||||
f_type_print_varspec_prefix (type, stream, show, 0);
|
||||
|
||||
fputs_filtered (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[strlen(varstring) - 1] == ')';
|
||||
f_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
|
||||
}
|
||||
|
||||
/* Print any asterisks or open-parentheses needed before the
|
||||
variable name (to describe its type).
|
||||
|
||||
On outermost call, pass 0 for PASSED_A_PTR.
|
||||
On outermost call, SHOW > 0 means should ignore
|
||||
any typename for TYPE and show its details.
|
||||
SHOW is always zero on recursive calls. */
|
||||
|
||||
void
|
||||
f_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
int show;
|
||||
int passed_a_ptr;
|
||||
{
|
||||
char *name;
|
||||
if (type == 0)
|
||||
return;
|
||||
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
return;
|
||||
|
||||
QUIT;
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
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)
|
||||
fprintf_filtered (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_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:
|
||||
/* These types need no prefix. They are listed here so that
|
||||
gcc -Wall will reveal any types that haven't been handled. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
f_type_print_args (type, stream)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
{
|
||||
int i;
|
||||
struct type **args;
|
||||
|
||||
fprintf_filtered (stream, "(");
|
||||
args = TYPE_ARG_TYPES (type);
|
||||
if (args != NULL)
|
||||
{
|
||||
if (args[1] == NULL)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1; args[i] != NULL && args[i]->code != TYPE_CODE_VOID; i++)
|
||||
{
|
||||
f_print_type (args[i], "", stream, -1, 0);
|
||||
if (args[i+1] == NULL)
|
||||
fprintf_filtered (stream, "...");
|
||||
else if (args[i+1]->code != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, ",");
|
||||
wrap_here (" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
/* Print any array sizes, function arguments or close parentheses
|
||||
needed after the variable name (to describe its type).
|
||||
Args work like c_type_print_varspec_prefix. */
|
||||
|
||||
static void
|
||||
f_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
int show;
|
||||
int passed_a_ptr;
|
||||
int demangled_args;
|
||||
{
|
||||
CORE_ADDR current_frame_addr = 0;
|
||||
int upper_bound,lower_bound;
|
||||
int lower_bound_was_default = 0;
|
||||
static int arrayprint_recurse_level = 0;
|
||||
int retcode;
|
||||
|
||||
if (type == 0)
|
||||
return;
|
||||
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
return;
|
||||
|
||||
QUIT;
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
arrayprint_recurse_level++;
|
||||
|
||||
if (arrayprint_recurse_level == 1)
|
||||
fprintf_filtered(stream,"(");
|
||||
else
|
||||
fprintf_filtered(stream,",");
|
||||
|
||||
retcode = f77_get_dynamic_lowerbound (type,&lower_bound);
|
||||
|
||||
lower_bound_was_default = 0;
|
||||
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
fprintf_filtered (stream,"???");
|
||||
else
|
||||
if (lower_bound == 1) /* The default */
|
||||
lower_bound_was_default = 1;
|
||||
else
|
||||
fprintf_filtered (stream,"%d",lower_bound);
|
||||
|
||||
if (lower_bound_was_default)
|
||||
lower_bound_was_default = 0;
|
||||
else
|
||||
fprintf_filtered(stream,":");
|
||||
|
||||
/* Make sure that, if we have an assumed size array, we
|
||||
print out a warning and print the upperbound as '*' */
|
||||
|
||||
if (TYPE_ARRAY_UPPER_BOUND_TYPE(type) == BOUND_CANNOT_BE_DETERMINED)
|
||||
fprintf_filtered (stream, "*");
|
||||
else
|
||||
{
|
||||
retcode = f77_get_dynamic_upperbound(type,&upper_bound);
|
||||
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
fprintf_filtered(stream,"???");
|
||||
else
|
||||
fprintf_filtered(stream,"%d",upper_bound);
|
||||
}
|
||||
|
||||
f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
|
||||
if (arrayprint_recurse_level == 1)
|
||||
fprintf_filtered (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);
|
||||
fprintf_filtered(stream,")");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, ")");
|
||||
|
||||
fprintf_filtered (stream, "()");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
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_LITERAL_STRING:
|
||||
case TYPE_CODE_STRING:
|
||||
/* These types do not need a suffix. They are listed so that
|
||||
gcc -Wall will report types that may not have been considered. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_equivalent_f77_float_type (type, stream)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
{
|
||||
/* Override type name "float" and make it the
|
||||
appropriate real. XLC stupidly outputs -12 as a type
|
||||
for real when it really should be outputting -18 */
|
||||
|
||||
switch (TYPE_LENGTH (type))
|
||||
{
|
||||
case 4:
|
||||
fprintf_filtered (stream, "real*4");
|
||||
break;
|
||||
|
||||
case 8:
|
||||
fprintf_filtered(stream,"real*8");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the name of the type (or the ultimate pointer target,
|
||||
function value or array element), or the description of a
|
||||
structure or union.
|
||||
|
||||
SHOW nonzero means don't print this type as just its name;
|
||||
show its real definition even if it has a name.
|
||||
SHOW zero means print just typename or struct tag if there is one
|
||||
SHOW negative means abbreviate structure elements.
|
||||
SHOW is decremented for printing of structure elements.
|
||||
|
||||
LEVEL is the depth to indent by.
|
||||
We increase it for some recursive calls. */
|
||||
|
||||
void
|
||||
f_type_print_base (type, stream, show, level)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
char *name;
|
||||
register int i;
|
||||
register int len;
|
||||
register int lastval;
|
||||
char *mangled_name;
|
||||
char *demangled_name;
|
||||
enum {s_none, s_public, s_private, s_protected} section_type;
|
||||
int retcode,upper_bound;
|
||||
QUIT;
|
||||
|
||||
wrap_here (" ");
|
||||
if (type == NULL)
|
||||
{
|
||||
fputs_filtered ("<type unknown>", 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 (type) != NULL))
|
||||
{
|
||||
/* Damn builtin types on RS6000! They call a float "float"
|
||||
so we gotta translate to appropriate F77'isms */
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||
print_equivalent_f77_float_type (type, stream);
|
||||
else
|
||||
fputs_filtered (TYPE_NAME (type), stream);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
fprintf_filtered (stream, "PTR TO -> ( ");
|
||||
f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
fprintf_filtered (stream, "VOID");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
fprintf_filtered (stream, "struct <unknown>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ERROR:
|
||||
fprintf_filtered (stream, "<unknown type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
/* This should not occur */
|
||||
fprintf_filtered (stream, "<range type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_CHAR:
|
||||
/* Override name "char" and make it "character" */
|
||||
fprintf_filtered (stream, "character");
|
||||
break;
|
||||
|
||||
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 (STREQ(TYPE_NAME(type),"char"))
|
||||
fprintf_filtered (stream,"character");
|
||||
else
|
||||
goto default_case;
|
||||
break;
|
||||
|
||||
case TYPE_CODE_COMPLEX:
|
||||
case TYPE_CODE_LITERAL_COMPLEX:
|
||||
fprintf_filtered (stream,"complex*");
|
||||
fprintf_filtered (stream,"%d",TYPE_LENGTH(type));
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
print_equivalent_f77_float_type(type,stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_LITERAL_STRING:
|
||||
fprintf_filtered (stream, "character*%d",
|
||||
TYPE_ARRAY_UPPER_BOUND_VALUE (type));
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRING:
|
||||
/* Strings may have dynamic upperbounds (lengths) like arrays */
|
||||
|
||||
if (TYPE_ARRAY_UPPER_BOUND_TYPE (type) == BOUND_CANNOT_BE_DETERMINED)
|
||||
fprintf_filtered("character*(*)");
|
||||
else
|
||||
{
|
||||
retcode = f77_get_dynamic_upperbound(type,&upper_bound);
|
||||
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
fprintf_filtered(stream,"character*???");
|
||||
else
|
||||
fprintf_filtered(stream,"character*%d",upper_bound);
|
||||
}
|
||||
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 (type) != NULL)
|
||||
fputs_filtered (TYPE_NAME (type), stream);
|
||||
else
|
||||
error ("Invalid type code (%d) in symbol table.", TYPE_CODE (type));
|
||||
break;
|
||||
}
|
||||
}
|
889
gdb/f-valprint.c
Normal file
889
gdb/f-valprint.c
Normal file
|
@ -0,0 +1,889 @@
|
|||
/* Support for printing Fortran values for GDB, the GNU debugger.
|
||||
Copyright 1993, 1994 Free Software Foundation, Inc.
|
||||
Contributed by Motorola. Adapted from the C definitions by Farooq Butt
|
||||
(fmbutt@engage.sps.mot.com), additionally worked over by Stan Shebs.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "demangle.h"
|
||||
#include "valprint.h"
|
||||
#include "language.h"
|
||||
#include "f-lang.h"
|
||||
#include "frame.h"
|
||||
|
||||
extern struct obstack dont_print_obstack;
|
||||
|
||||
extern unsigned int print_max; /* No of array elements to print */
|
||||
|
||||
int f77_array_offset_tbl[MAX_FORTRAN_DIMS+1][2];
|
||||
|
||||
/* Array which holds offsets to be applied to get a row's elements
|
||||
for a given array. Array also holds the size of each subarray. */
|
||||
|
||||
/* The following macro gives us the size of the nth dimension, Where
|
||||
n is 1 based. */
|
||||
|
||||
#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1])
|
||||
|
||||
/* The following gives us the offset for row n where n is 1-based. */
|
||||
|
||||
#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0])
|
||||
|
||||
int
|
||||
f77_get_dynamic_lowerbound (type, lower_bound)
|
||||
struct type *type;
|
||||
int *lower_bound;
|
||||
{
|
||||
CORE_ADDR current_frame_addr;
|
||||
CORE_ADDR ptr_to_lower_bound;
|
||||
|
||||
switch (TYPE_ARRAY_LOWER_BOUND_TYPE (type))
|
||||
{
|
||||
case BOUND_BY_VALUE_ON_STACK:
|
||||
current_frame_addr = selected_frame->frame;
|
||||
if (current_frame_addr > 0)
|
||||
{
|
||||
*lower_bound =
|
||||
read_memory_integer (current_frame_addr +
|
||||
TYPE_ARRAY_LOWER_BOUND_VALUE (type),4);
|
||||
}
|
||||
else
|
||||
{
|
||||
*lower_bound = DEFAULT_LOWER_BOUND;
|
||||
return BOUND_FETCH_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case BOUND_SIMPLE:
|
||||
*lower_bound = TYPE_ARRAY_LOWER_BOUND_VALUE (type);
|
||||
break;
|
||||
|
||||
case BOUND_CANNOT_BE_DETERMINED:
|
||||
error("Lower bound may not be '*' in F77");
|
||||
break;
|
||||
|
||||
case BOUND_BY_REF_ON_STACK:
|
||||
current_frame_addr = selected_frame->frame;
|
||||
if (current_frame_addr > 0)
|
||||
{
|
||||
ptr_to_lower_bound =
|
||||
read_memory_integer (current_frame_addr +
|
||||
TYPE_ARRAY_LOWER_BOUND_VALUE (type),
|
||||
4);
|
||||
*lower_bound = read_memory_integer(ptr_to_lower_bound);
|
||||
}
|
||||
else
|
||||
{
|
||||
*lower_bound = DEFAULT_LOWER_BOUND;
|
||||
return BOUND_FETCH_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case BOUND_BY_REF_IN_REG:
|
||||
case BOUND_BY_VALUE_IN_REG:
|
||||
default:
|
||||
error ("??? unhandled dynamic array bound type ???");
|
||||
break;
|
||||
}
|
||||
return BOUND_FETCH_OK;
|
||||
}
|
||||
|
||||
int
|
||||
f77_get_dynamic_upperbound (type, upper_bound)
|
||||
struct type *type;
|
||||
int *upper_bound;
|
||||
{
|
||||
CORE_ADDR current_frame_addr = 0;
|
||||
CORE_ADDR ptr_to_upper_bound;
|
||||
|
||||
switch (TYPE_ARRAY_UPPER_BOUND_TYPE (type))
|
||||
{
|
||||
case BOUND_BY_VALUE_ON_STACK:
|
||||
current_frame_addr = selected_frame->frame;
|
||||
if (current_frame_addr > 0)
|
||||
{
|
||||
*upper_bound =
|
||||
read_memory_integer (current_frame_addr +
|
||||
TYPE_ARRAY_UPPER_BOUND_VALUE (type),4);
|
||||
}
|
||||
else
|
||||
{
|
||||
*upper_bound = DEFAULT_UPPER_BOUND;
|
||||
return BOUND_FETCH_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case BOUND_SIMPLE:
|
||||
*upper_bound = TYPE_ARRAY_UPPER_BOUND_VALUE (type);
|
||||
break;
|
||||
|
||||
case BOUND_CANNOT_BE_DETERMINED:
|
||||
/* we have an assumed size array on our hands. Assume that
|
||||
upper_bound == lower_bound so that we show at least
|
||||
1 element.If the user wants to see more elements, let
|
||||
him manually ask for 'em and we'll subscript the
|
||||
array and show him */
|
||||
f77_get_dynamic_lowerbound (type, &upper_bound);
|
||||
break;
|
||||
|
||||
case BOUND_BY_REF_ON_STACK:
|
||||
current_frame_addr = selected_frame->frame;
|
||||
if (current_frame_addr > 0)
|
||||
{
|
||||
ptr_to_upper_bound =
|
||||
read_memory_integer (current_frame_addr +
|
||||
TYPE_ARRAY_UPPER_BOUND_VALUE (type),
|
||||
4);
|
||||
*upper_bound = read_memory_integer(ptr_to_upper_bound);
|
||||
}
|
||||
else
|
||||
{
|
||||
*upper_bound = DEFAULT_UPPER_BOUND;
|
||||
return BOUND_FETCH_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case BOUND_BY_REF_IN_REG:
|
||||
case BOUND_BY_VALUE_IN_REG:
|
||||
default:
|
||||
error ("??? unhandled dynamic array bound type ???");
|
||||
break;
|
||||
}
|
||||
return BOUND_FETCH_OK;
|
||||
}
|
||||
|
||||
/* Obtain F77 adjustable array dimensions */
|
||||
|
||||
void
|
||||
f77_get_dynamic_length_of_aggregate (type)
|
||||
struct type *type;
|
||||
{
|
||||
int upper_bound = -1;
|
||||
int lower_bound = 1;
|
||||
unsigned int current_total = 1;
|
||||
int retcode;
|
||||
|
||||
/* Recursively go all the way down into a possibly
|
||||
multi-dimensional F77 array
|
||||
and get the bounds. For simple arrays, this is pretty easy
|
||||
but when the bounds are dynamic, we must be very careful
|
||||
to add up all the lengths correctly. Not doing this right
|
||||
will lead to horrendous-looking arrays in parameter lists.
|
||||
|
||||
This function also works for strings which behave very
|
||||
similarly to arrays. */
|
||||
|
||||
if (TYPE_CODE(TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY
|
||||
|| TYPE_CODE(TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRING)
|
||||
f77_get_dynamic_length_of_aggregate (TYPE_TARGET_TYPE (type));
|
||||
|
||||
/* Recursion ends here, start setting up lengths. */
|
||||
retcode = f77_get_dynamic_lowerbound (type, &lower_bound);
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
error ("Cannot obtain valid array lower bound");
|
||||
|
||||
retcode = f77_get_dynamic_upperbound (type, &upper_bound);
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
error ("Cannot obtain valid array upper bound");
|
||||
|
||||
/* Patch in a valid length value. */
|
||||
|
||||
TYPE_LENGTH (type) =
|
||||
(upper_bound - lower_bound + 1) * TYPE_LENGTH (TYPE_TARGET_TYPE (type));
|
||||
}
|
||||
|
||||
/* Print a FORTRAN COMPLEX value of type TYPE, pointed to in GDB by VALADDR,
|
||||
on STREAM. which_complex indicates precision, which may be regular,
|
||||
*16, or *32 */
|
||||
|
||||
void
|
||||
f77_print_cmplx (valaddr, type, stream, which_complex)
|
||||
char *valaddr;
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
int which_complex;
|
||||
{
|
||||
float *f1,*f2;
|
||||
double *d1, *d2;
|
||||
int i;
|
||||
|
||||
switch (which_complex)
|
||||
{
|
||||
case TARGET_COMPLEX_BIT:
|
||||
f1 = (float *) valaddr;
|
||||
f2 = (float *) (valaddr + sizeof(float));
|
||||
fprintf_filtered (stream, "(%.7e,%.7e)", *f1, *f2);
|
||||
break;
|
||||
|
||||
case TARGET_DOUBLE_COMPLEX_BIT:
|
||||
d1 = (double *) valaddr;
|
||||
d2 = (double *) (valaddr + sizeof(double));
|
||||
fprintf_filtered (stream, "(%.16e,%.16e)", *d1, *d2);
|
||||
break;
|
||||
#if 0
|
||||
case TARGET_EXT_COMPLEX_BIT:
|
||||
fprintf_filtered (stream, "<complex*32 format unavailable, "
|
||||
"printing raw data>\n");
|
||||
|
||||
fprintf_filtered (stream, "( [ ");
|
||||
|
||||
for (i = 0;i<4;i++)
|
||||
fprintf_filtered (stream, "0x%x ",
|
||||
* ( (unsigned int *) valaddr+i));
|
||||
|
||||
fprintf_filtered (stream, "],\n [ ");
|
||||
|
||||
for (i=4;i<8;i++)
|
||||
fprintf_filtered (stream, "0x%x ",
|
||||
* ((unsigned int *) valaddr+i));
|
||||
|
||||
fprintf_filtered (stream, "] )");
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf_filtered (stream, "<cannot handle complex of this type>");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function that sets up the array offset,size table for the array
|
||||
type "type". */
|
||||
|
||||
void
|
||||
f77_create_arrayprint_offset_tbl (type, stream)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
{
|
||||
struct type *tmp_type;
|
||||
int eltlen;
|
||||
int ndimen = 1;
|
||||
int upper, lower, retcode;
|
||||
|
||||
tmp_type = type;
|
||||
|
||||
while ((TYPE_CODE (tmp_type) == TYPE_CODE_ARRAY))
|
||||
{
|
||||
if (TYPE_ARRAY_UPPER_BOUND_TYPE (tmp_type) == BOUND_CANNOT_BE_DETERMINED)
|
||||
fprintf_filtered (stream, "<assumed size array> ");
|
||||
|
||||
retcode = f77_get_dynamic_upperbound (tmp_type, &upper);
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
error ("Cannot obtain dynamic upper bound");
|
||||
|
||||
retcode = f77_get_dynamic_lowerbound(tmp_type,&lower);
|
||||
if (retcode == BOUND_FETCH_ERROR)
|
||||
error("Cannot obtain dynamic lower bound");
|
||||
|
||||
F77_DIM_SIZE (ndimen) = upper - lower + 1;
|
||||
|
||||
if (ndimen == 1)
|
||||
F77_DIM_OFFSET (ndimen) = 1;
|
||||
else
|
||||
F77_DIM_OFFSET (ndimen) =
|
||||
F77_DIM_OFFSET (ndimen - 1) * F77_DIM_SIZE(ndimen - 1);
|
||||
|
||||
tmp_type = TYPE_TARGET_TYPE (tmp_type);
|
||||
ndimen++;
|
||||
}
|
||||
|
||||
eltlen = TYPE_LENGTH (tmp_type);
|
||||
|
||||
/* Now we multiply eltlen by all the offsets, so that later we
|
||||
can print out array elements correctly. Up till now we
|
||||
know an offset to apply to get the item but we also
|
||||
have to know how much to add to get to the next item */
|
||||
|
||||
tmp_type = type;
|
||||
ndimen = 1;
|
||||
|
||||
while ((TYPE_CODE (tmp_type) == TYPE_CODE_ARRAY))
|
||||
{
|
||||
F77_DIM_OFFSET (ndimen) *= eltlen;
|
||||
ndimen++;
|
||||
tmp_type = TYPE_TARGET_TYPE (tmp_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Actual function which prints out F77 arrays, Valaddr == address in
|
||||
the superior. Address == the address in the inferior. */
|
||||
|
||||
void
|
||||
f77_print_array_1 (nss, ndimensions, type, valaddr, address,
|
||||
stream, format, deref_ref, recurse, pretty)
|
||||
int nss;
|
||||
int ndimensions;
|
||||
char *valaddr;
|
||||
struct type *type;
|
||||
CORE_ADDR address;
|
||||
FILE *stream;
|
||||
int format;
|
||||
int deref_ref;
|
||||
int recurse;
|
||||
enum val_prettyprint pretty;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (nss != ndimensions)
|
||||
{
|
||||
for (i = 0; i< F77_DIM_SIZE(nss); i++)
|
||||
{
|
||||
fprintf_filtered (stream, "( ");
|
||||
f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type),
|
||||
valaddr + i * F77_DIM_OFFSET (nss),
|
||||
address + i * F77_DIM_OFFSET (nss),
|
||||
stream, format, deref_ref, recurse, pretty, i);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; (i < F77_DIM_SIZE (nss) && i < print_max); i++)
|
||||
{
|
||||
val_print (TYPE_TARGET_TYPE (type),
|
||||
valaddr + i * F77_DIM_OFFSET (ndimensions),
|
||||
address + i * F77_DIM_OFFSET (ndimensions),
|
||||
stream, format, deref_ref, recurse, pretty);
|
||||
|
||||
if (i != (F77_DIM_SIZE (nss) - 1))
|
||||
fprintf_filtered (stream, ", ");
|
||||
|
||||
if (i == print_max - 1)
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function gets called to print an F77 array, we set up some
|
||||
stuff and then immediately call f77_print_array_1() */
|
||||
|
||||
void
|
||||
f77_print_array (type, valaddr, address, stream, format, deref_ref, recurse,
|
||||
pretty)
|
||||
struct type *type;
|
||||
char *valaddr;
|
||||
CORE_ADDR address;
|
||||
FILE *stream;
|
||||
int format;
|
||||
int deref_ref;
|
||||
int recurse;
|
||||
enum val_prettyprint pretty;
|
||||
{
|
||||
int array_size_array[MAX_FORTRAN_DIMS+1];
|
||||
int ndimensions;
|
||||
|
||||
ndimensions = calc_f77_array_dims (type);
|
||||
|
||||
if (ndimensions > MAX_FORTRAN_DIMS || ndimensions < 0)
|
||||
error ("Type node corrupt! F77 arrays cannot have %d subscripts (%d Max)",
|
||||
ndimensions, MAX_FORTRAN_DIMS);
|
||||
|
||||
/* Since F77 arrays are stored column-major, we set up an
|
||||
offset table to get at the various row's elements. The
|
||||
offset table contains entries for both offset and subarray size. */
|
||||
|
||||
f77_create_arrayprint_offset_tbl (type, stream);
|
||||
|
||||
f77_print_array_1 (1, ndimensions, type, valaddr, address, stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
}
|
||||
|
||||
|
||||
/* Print data of type TYPE located at VALADDR (within GDB), which came from
|
||||
the inferior at address ADDRESS, onto stdio stream STREAM according to
|
||||
FORMAT (a letter or 0 for natural format). The data at VALADDR is in
|
||||
target byte order.
|
||||
|
||||
If the data are a string pointer, returns the number of string characters
|
||||
printed.
|
||||
|
||||
If DEREF_REF is nonzero, then dereference references, otherwise just print
|
||||
them like pointers.
|
||||
|
||||
The PRETTY parameter controls prettyprinting. */
|
||||
|
||||
int
|
||||
f_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
|
||||
pretty)
|
||||
struct type *type;
|
||||
char *valaddr;
|
||||
CORE_ADDR address;
|
||||
FILE *stream;
|
||||
int format;
|
||||
int deref_ref;
|
||||
int recurse;
|
||||
enum val_prettyprint pretty;
|
||||
{
|
||||
register unsigned int i = 0; /* Number of characters printed */
|
||||
unsigned len;
|
||||
struct type *elttype;
|
||||
unsigned eltlen;
|
||||
LONGEST val;
|
||||
struct internalvar *ivar;
|
||||
char *localstr;
|
||||
unsigned char c;
|
||||
CORE_ADDR addr;
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_LITERAL_STRING:
|
||||
/* It is trivial to print out F77 strings allocated in the
|
||||
superior process. The address field is actually a
|
||||
pointer to the bytes of the literal. For an internalvar,
|
||||
valaddr points to a ptr. which points to
|
||||
VALUE_LITERAL_DATA(value->internalvar->value)
|
||||
and for straight literals (i.e. of the form 'hello world'),
|
||||
valaddr points a ptr to VALUE_LITERAL_DATA(value). */
|
||||
|
||||
/* First deref. valaddr */
|
||||
|
||||
addr = * (CORE_ADDR *) valaddr;
|
||||
|
||||
if (addr)
|
||||
{
|
||||
len = TYPE_LENGTH (type);
|
||||
localstr = alloca (len + 1);
|
||||
strncpy (localstr, addr, len);
|
||||
localstr[len] = '\0';
|
||||
fprintf_filtered (stream, "'%s'", localstr);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "Unable to print literal F77 string");
|
||||
break;
|
||||
|
||||
/* Strings are a little bit funny. They can be viewed as
|
||||
monolithic arrays that are dealt with as atomic data
|
||||
items. As such they are the only atomic data items whose
|
||||
contents are not located in the superior process. Instead
|
||||
instead of having the actual data, they contain pointers
|
||||
to addresses in the inferior where data is located. Thus
|
||||
instead of using valaddr, we use address. */
|
||||
|
||||
case TYPE_CODE_STRING:
|
||||
f77_get_dynamic_length_of_aggregate (type);
|
||||
val_print_string (address, TYPE_LENGTH (type), stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
fprintf_filtered (stream, "(");
|
||||
f77_print_array (type, valaddr, address, stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
fprintf_filtered (stream, ")");
|
||||
break;
|
||||
#if 0
|
||||
/* Array of unspecified length: treat like pointer to first elt. */
|
||||
valaddr = (char *) &address;
|
||||
/* FALL THROUGH */
|
||||
#endif
|
||||
case TYPE_CODE_PTR:
|
||||
if (format && format != 's')
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = unpack_pointer (type, valaddr);
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
|
||||
if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
|
||||
{
|
||||
/* Try to print what function it points to. */
|
||||
print_address_demangle (addr, stream, demangle);
|
||||
/* Return value is irrelevant except for string pointers. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (addressprint && format != 's')
|
||||
fprintf_filtered (stream, "0x%x", addr);
|
||||
|
||||
/* For a pointer to char or unsigned char, also print the string
|
||||
pointed to, unless pointer is null. */
|
||||
if (TYPE_LENGTH (elttype) == 1
|
||||
&& TYPE_CODE (elttype) == TYPE_CODE_INT
|
||||
&& (format == 0 || format == 's')
|
||||
&& addr != 0)
|
||||
i = val_print_string (addr, 0, stream);
|
||||
|
||||
/* Return number of characters printed, plus one for the
|
||||
terminating null if we have "reached the end". */
|
||||
return (i + (print_max && i != print_max));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
/* FIXME, we should consider, at least for ANSI C language, eliminating
|
||||
the distinction made between FUNCs and POINTERs to FUNCs. */
|
||||
fprintf_filtered (stream, "{");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, "} ");
|
||||
/* Try to print what function it points to, and its address. */
|
||||
print_address_demangle (address, stream, demangle);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
else
|
||||
{
|
||||
val_print_type_code_int (type, valaddr, stream);
|
||||
/* C and C++ has no single byte int type, char is used instead.
|
||||
Since we don't know whether the value is really intended to
|
||||
be used as an integer or a character, print the character
|
||||
equivalent as well. */
|
||||
if (TYPE_LENGTH (type) == 1)
|
||||
{
|
||||
fputs_filtered (" ", stream);
|
||||
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
|
||||
stream);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
if (format)
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
else
|
||||
print_floating (valaddr, type, stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
fprintf_filtered (stream, "VOID");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ERROR:
|
||||
fprintf_filtered (stream, "<error type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
/* FIXME, we should not ever have to print one of these yet. */
|
||||
fprintf_filtered (stream, "<range type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BOOL:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
else
|
||||
{
|
||||
val = 0;
|
||||
switch (TYPE_LENGTH(type))
|
||||
{
|
||||
case 1:
|
||||
val = unpack_long (builtin_type_f_logical_s1, valaddr);
|
||||
break ;
|
||||
|
||||
case 2:
|
||||
val = unpack_long (builtin_type_f_logical_s2, valaddr);
|
||||
break ;
|
||||
|
||||
case 4:
|
||||
val = unpack_long (builtin_type_f_logical, valaddr);
|
||||
break ;
|
||||
|
||||
default:
|
||||
error ("Logicals of length %d bytes not supported",
|
||||
TYPE_LENGTH (type));
|
||||
|
||||
}
|
||||
|
||||
if (val == 0)
|
||||
fprintf_filtered (stream, ".FALSE.");
|
||||
else
|
||||
if (val == 1)
|
||||
fprintf_filtered (stream, ".TRUE.");
|
||||
else
|
||||
/* Not a legitimate logical type, print as an integer. */
|
||||
{
|
||||
/* Bash the type code temporarily. */
|
||||
TYPE_CODE (type) = TYPE_CODE_INT;
|
||||
f_val_print (type, valaddr, address, stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
/* Restore the type code so later uses work as intended. */
|
||||
TYPE_CODE (type) = TYPE_CODE_BOOL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_LITERAL_COMPLEX:
|
||||
/* We know that the literal complex is stored in the superior
|
||||
process not the inferior and that it is 16 bytes long.
|
||||
Just like the case above with a literal array, the
|
||||
bytes for the the literal complex number are stored
|
||||
at the address pointed to by valaddr */
|
||||
|
||||
if (TYPE_LENGTH(type) == 32)
|
||||
error("Cannot currently print out complex*32 literals");
|
||||
|
||||
/* First deref. valaddr */
|
||||
|
||||
addr = * (CORE_ADDR *) valaddr;
|
||||
|
||||
if (addr)
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
|
||||
if (TYPE_LENGTH(type) == 16)
|
||||
{
|
||||
fprintf_filtered (stream, "%.16f", * (double *) addr);
|
||||
fprintf_filtered (stream, ", %.16f", * (double *)
|
||||
(addr + sizeof(double)));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "%.8f", * (float *) addr);
|
||||
fprintf_filtered (stream, ", %.8f", * (float *)
|
||||
(addr + sizeof(float)));
|
||||
}
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "Unable to print literal F77 array");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_COMPLEX:
|
||||
switch (TYPE_LENGTH (type))
|
||||
{
|
||||
case 8:
|
||||
f77_print_cmplx (valaddr, type, stream, TARGET_COMPLEX_BIT);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
f77_print_cmplx(valaddr, type, stream, TARGET_DOUBLE_COMPLEX_BIT);
|
||||
break;
|
||||
#if 0
|
||||
case 32:
|
||||
f77_print_cmplx(valaddr, type, stream, TARGET_EXT_COMPLEX_BIT);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error ("Cannot print out complex*%d variables", TYPE_LENGTH(type));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
/* This happens (without TYPE_FLAG_STUB set) on systems which don't use
|
||||
dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar"
|
||||
and no complete type for struct foo in that file. */
|
||||
fprintf_filtered (stream, "<incomplete type>");
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid F77 type code %d in symbol table.", TYPE_CODE (type));
|
||||
}
|
||||
fflush (stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
list_all_visible_commons (funname)
|
||||
char *funname;
|
||||
{
|
||||
SAVED_F77_COMMON_PTR tmp;
|
||||
|
||||
tmp = head_common_list;
|
||||
|
||||
printf_filtered ("All COMMON blocks visible at this level:\n\n");
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (STREQ(tmp->owning_function,funname))
|
||||
printf_filtered ("%s\n", tmp->name);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is used to print out the values in a given COMMON
|
||||
block. It will always use the most local common block of the
|
||||
given name */
|
||||
|
||||
static void
|
||||
info_common_command (comname, from_tty)
|
||||
char *comname;
|
||||
int from_tty;
|
||||
{
|
||||
SAVED_F77_COMMON_PTR the_common;
|
||||
COMMON_ENTRY_PTR entry;
|
||||
struct frame_info *fi;
|
||||
register char *funname = 0;
|
||||
struct symbol *func;
|
||||
char *cmd;
|
||||
|
||||
/* We have been told to display the contents of F77 COMMON
|
||||
block supposedly visible in this function. Let us
|
||||
first make sure that it is visible and if so, let
|
||||
us display its contents */
|
||||
|
||||
fi = selected_frame;
|
||||
|
||||
if (fi == NULL)
|
||||
error ("No frame selected");
|
||||
|
||||
/* The following is generally ripped off from stack.c's routine
|
||||
print_frame_info() */
|
||||
|
||||
func = find_pc_function (fi->pc);
|
||||
if (func)
|
||||
{
|
||||
/* In certain pathological cases, the symtabs give the wrong
|
||||
function (when we are in the first function in a file which
|
||||
is compiled without debugging symbols, the previous function
|
||||
is compiled with debugging symbols, and the "foo.o" symbol
|
||||
that is supposed to tell us where the file with debugging symbols
|
||||
ends has been truncated by ar because it is longer than 15
|
||||
characters).
|
||||
|
||||
So look in the minimal symbol tables as well, and if it comes
|
||||
up with a larger address for the function use that instead.
|
||||
I don't think this can ever cause any problems; there shouldn't
|
||||
be any minimal symbols in the middle of a function.
|
||||
FIXME: (Not necessarily true. What about text labels) */
|
||||
|
||||
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
|
||||
|
||||
if (msymbol != NULL
|
||||
&& (SYMBOL_VALUE_ADDRESS (msymbol)
|
||||
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
|
||||
funname = SYMBOL_NAME (msymbol);
|
||||
else
|
||||
funname = SYMBOL_NAME (func);
|
||||
}
|
||||
else
|
||||
{
|
||||
register struct minimal_symbol *msymbol =
|
||||
lookup_minimal_symbol_by_pc (fi->pc);
|
||||
|
||||
if (msymbol != NULL)
|
||||
funname = SYMBOL_NAME (msymbol);
|
||||
}
|
||||
|
||||
/* If comnname is NULL, we assume the user wishes to see the
|
||||
which COMMON blocks are visible here and then return */
|
||||
|
||||
if (strlen (comname) == 0)
|
||||
{
|
||||
list_all_visible_commons (funname);
|
||||
return;
|
||||
}
|
||||
|
||||
the_common = find_common_for_function (comname,funname);
|
||||
|
||||
if (the_common)
|
||||
{
|
||||
if (STREQ(comname,BLANK_COMMON_NAME_LOCAL))
|
||||
printf_filtered ("Contents of blank COMMON block:\n");
|
||||
else
|
||||
printf_filtered ("Contents of F77 COMMON block '%s':\n",comname);
|
||||
|
||||
printf_filtered ("\n");
|
||||
entry = the_common->entries;
|
||||
|
||||
while (entry != NULL)
|
||||
{
|
||||
printf_filtered ("%s = ",SYMBOL_NAME(entry->symbol));
|
||||
print_variable_value (entry->symbol,fi,stdout);
|
||||
printf_filtered ("\n");
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf_filtered ("Cannot locate the common block %s in function '%s'\n",
|
||||
comname, funname);
|
||||
}
|
||||
|
||||
/* This function is used to determine whether there is a
|
||||
F77 common block visible at the current scope called 'comname'. */
|
||||
|
||||
int
|
||||
there_is_a_visible_common_named (comname)
|
||||
char *comname;
|
||||
{
|
||||
SAVED_F77_COMMON_PTR the_common;
|
||||
COMMON_ENTRY_PTR entry;
|
||||
struct frame_info *fi;
|
||||
register char *funname = 0;
|
||||
struct symbol *func;
|
||||
|
||||
if (comname == NULL)
|
||||
error ("Cannot deal with NULL common name!");
|
||||
|
||||
fi = selected_frame;
|
||||
|
||||
if (fi == NULL)
|
||||
error ("No frame selected");
|
||||
|
||||
/* The following is generally ripped off from stack.c's routine
|
||||
print_frame_info() */
|
||||
|
||||
func = find_pc_function (fi->pc);
|
||||
if (func)
|
||||
{
|
||||
/* In certain pathological cases, the symtabs give the wrong
|
||||
function (when we are in the first function in a file which
|
||||
is compiled without debugging symbols, the previous function
|
||||
is compiled with debugging symbols, and the "foo.o" symbol
|
||||
that is supposed to tell us where the file with debugging symbols
|
||||
ends has been truncated by ar because it is longer than 15
|
||||
characters).
|
||||
|
||||
So look in the minimal symbol tables as well, and if it comes
|
||||
up with a larger address for the function use that instead.
|
||||
I don't think this can ever cause any problems; there shouldn't
|
||||
be any minimal symbols in the middle of a function.
|
||||
FIXME: (Not necessarily true. What about text labels) */
|
||||
|
||||
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
|
||||
|
||||
if (msymbol != NULL
|
||||
&& (SYMBOL_VALUE_ADDRESS (msymbol)
|
||||
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
|
||||
funname = SYMBOL_NAME (msymbol);
|
||||
else
|
||||
funname = SYMBOL_NAME (func);
|
||||
}
|
||||
else
|
||||
{
|
||||
register struct minimal_symbol *msymbol =
|
||||
lookup_minimal_symbol_by_pc (fi->pc);
|
||||
|
||||
if (msymbol != NULL)
|
||||
funname = SYMBOL_NAME (msymbol);
|
||||
}
|
||||
|
||||
the_common = find_common_for_function (comname, funname);
|
||||
|
||||
return (the_common ? 1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_f_valprint ()
|
||||
{
|
||||
add_info ("common", info_common_command,
|
||||
"Print out the values contained in a Fortran COMMON block.");
|
||||
}
|
|
@ -487,6 +487,86 @@ create_set_type (result_type, domain_type)
|
|||
return (result_type);
|
||||
}
|
||||
|
||||
/* Create an F77 literal complex type composed of the two types we are
|
||||
given as arguments. */
|
||||
|
||||
struct type *
|
||||
f77_create_literal_complex_type (type_arg1, type_arg2)
|
||||
struct type *type_arg1;
|
||||
struct type *type_arg2;
|
||||
{
|
||||
struct type *result;
|
||||
|
||||
/* First make sure that the 2 components of the complex
|
||||
number both have the same type */
|
||||
|
||||
if (TYPE_CODE (type_arg1) != TYPE_CODE (type_arg2))
|
||||
error ("Both components of a F77 complex number must have the same type!");
|
||||
|
||||
result = alloc_type (TYPE_OBJFILE (type_arg1));
|
||||
|
||||
TYPE_CODE (result) = TYPE_CODE_LITERAL_COMPLEX;
|
||||
TYPE_LENGTH (result) = TYPE_LENGTH(type_arg1) * 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Create a F77 LITERAL string type supplied by the user from the keyboard.
|
||||
|
||||
Elements will be of type ELEMENT_TYPE, the indices will be of type
|
||||
RANGE_TYPE.
|
||||
|
||||
FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
|
||||
sure it is TYPE_CODE_UNDEF before we bash it into an array type?
|
||||
|
||||
This is a total clone of create_array_type() except that there are
|
||||
a few simplyfing assumptions (e.g all bound types are simple). */
|
||||
|
||||
struct type *
|
||||
f77_create_literal_string_type (result_type, range_type)
|
||||
struct type *result_type;
|
||||
struct type *range_type;
|
||||
{
|
||||
int low_bound;
|
||||
int high_bound;
|
||||
|
||||
if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
|
||||
{
|
||||
/* FIXME: We only handle range types at the moment. Complain and
|
||||
create a dummy range type to use. */
|
||||
warning ("internal error: array index type must be a range type");
|
||||
range_type = lookup_fundamental_type (TYPE_OBJFILE (range_type),
|
||||
FT_INTEGER);
|
||||
range_type = create_range_type ((struct type *) NULL, range_type, 0, 0);
|
||||
}
|
||||
if (result_type == NULL)
|
||||
result_type = alloc_type (TYPE_OBJFILE (range_type));
|
||||
TYPE_CODE (result_type) = TYPE_CODE_LITERAL_STRING;
|
||||
TYPE_TARGET_TYPE (result_type) = builtin_type_f_character;
|
||||
low_bound = TYPE_FIELD_BITPOS (range_type, 0);
|
||||
high_bound = TYPE_FIELD_BITPOS (range_type, 1);
|
||||
|
||||
/* Safely can assume that all bound types are simple */
|
||||
|
||||
TYPE_LENGTH (result_type) =
|
||||
TYPE_LENGTH (builtin_type_f_character) * (high_bound - low_bound + 1);
|
||||
|
||||
TYPE_NFIELDS (result_type) = 1;
|
||||
TYPE_FIELDS (result_type) =
|
||||
(struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
|
||||
memset (TYPE_FIELDS (result_type), 0, sizeof (struct field));
|
||||
TYPE_FIELD_TYPE (result_type, 0) = range_type;
|
||||
TYPE_VPTR_FIELDNO (result_type) = -1;
|
||||
|
||||
/* Remember that all literal strings in F77 are of the
|
||||
character*N type. */
|
||||
|
||||
TYPE_ARRAY_LOWER_BOUND_TYPE (result_type) = BOUND_SIMPLE;
|
||||
TYPE_ARRAY_UPPER_BOUND_TYPE (result_type) = BOUND_SIMPLE;
|
||||
|
||||
return result_type;
|
||||
}
|
||||
|
||||
/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE.
|
||||
A MEMBER is a wierd thing -- it amounts to a typed offset into
|
||||
a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't
|
||||
|
|
|
@ -80,9 +80,7 @@ enum type_code
|
|||
TYPE_CODE_FUNC, /* Function type */
|
||||
TYPE_CODE_INT, /* Integer type */
|
||||
|
||||
/* Floating type. This is *NOT* a complex type. Complex types, when
|
||||
we have them, will have their own type code (or TYPE_CODE_ERROR if
|
||||
we can parse a complex type but not manipulate it). There are parts
|
||||
/* Floating type. This is *NOT* a complex type. Beware, there are parts
|
||||
of GDB which bogusly assume that TYPE_CODE_FLT can mean complex. */
|
||||
TYPE_CODE_FLT,
|
||||
|
||||
|
@ -119,7 +117,12 @@ enum type_code
|
|||
|
||||
/* Boolean type. 0 is false, 1 is true, and other values are non-boolean
|
||||
(e.g. FORTRAN "logical" used as unsigned int). */
|
||||
TYPE_CODE_BOOL
|
||||
TYPE_CODE_BOOL,
|
||||
|
||||
/* Fortran */
|
||||
TYPE_CODE_COMPLEX, /* Complex float */
|
||||
TYPE_CODE_LITERAL_COMPLEX, /* */
|
||||
TYPE_CODE_LITERAL_STRING /* */
|
||||
};
|
||||
|
||||
/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
|
||||
|
@ -182,6 +185,17 @@ struct type
|
|||
|
||||
unsigned length;
|
||||
|
||||
/* FIXME, these should probably be restricted to a Fortran-specific
|
||||
field in some fashion. */
|
||||
#define BOUND_CANNOT_BE_DETERMINED 5
|
||||
#define BOUND_BY_REF_ON_STACK 4
|
||||
#define BOUND_BY_VALUE_ON_STACK 3
|
||||
#define BOUND_BY_REF_IN_REG 2
|
||||
#define BOUND_BY_VALUE_IN_REG 1
|
||||
#define BOUND_SIMPLE 0
|
||||
int upper_bound_type;
|
||||
int lower_bound_type;
|
||||
|
||||
/* Every type is now associated with a particular objfile, and the
|
||||
type is allocated on the type_obstack for that objfile. One problem
|
||||
however, is that there are times when gdb allocates new types while
|
||||
|
@ -486,6 +500,17 @@ allocate_cplus_struct_type PARAMS ((struct type *));
|
|||
by force_to_range_type. */
|
||||
#define TYPE_DUMMY_RANGE(type) ((type)->vptr_fieldno)
|
||||
|
||||
/* Moto-specific stuff for FORTRAN arrays */
|
||||
|
||||
#define TYPE_ARRAY_UPPER_BOUND_TYPE(thistype) (thistype)->upper_bound_type
|
||||
#define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) (thistype)->lower_bound_type
|
||||
|
||||
#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
|
||||
(TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),1))
|
||||
|
||||
#define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
|
||||
(TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),0))
|
||||
|
||||
/* C++ */
|
||||
|
||||
#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
|
||||
|
@ -605,6 +630,23 @@ extern struct type *builtin_type_chill_long;
|
|||
extern struct type *builtin_type_chill_ulong;
|
||||
extern struct type *builtin_type_chill_real;
|
||||
|
||||
/* Fortran (F77) types */
|
||||
|
||||
extern struct type *builtin_type_f_character;
|
||||
extern struct type *builtin_type_f_integer;
|
||||
extern struct type *builtin_type_f_logical;
|
||||
extern struct type *builtin_type_f_logical_s1;
|
||||
extern struct type *builtin_type_f_logical_s2;
|
||||
extern struct type *builtin_type_f_integer;
|
||||
extern struct type *builtin_type_f_integer_s2;
|
||||
extern struct type *builtin_type_f_real;
|
||||
extern struct type *builtin_type_f_real_s8;
|
||||
extern struct type *builtin_type_f_real_s16;
|
||||
extern struct type *builtin_type_f_complex_s8;
|
||||
extern struct type *builtin_type_f_complex_s16;
|
||||
extern struct type *builtin_type_f_complex_s32;
|
||||
extern struct type *builtin_type_f_void;
|
||||
|
||||
/* Maximum and minimum values of built-in types */
|
||||
|
||||
#define MAX_OF_TYPE(t) \
|
||||
|
|
|
@ -166,6 +166,7 @@ set_language_command (ignore, from_tty)
|
|||
printf_unfiltered ("c Use the C language\n");
|
||||
printf_unfiltered ("c++ Use the C++ language\n");
|
||||
printf_unfiltered ("chill Use the Chill language\n");
|
||||
printf_unfiltered ("fortran Use the Fortran language\n");
|
||||
printf_unfiltered ("modula-2 Use the Modula-2 language\n");
|
||||
/* Restore the silly string. */
|
||||
set_language(current_language->la_language);
|
||||
|
|
|
@ -34,6 +34,9 @@ struct objfile;
|
|||
#define _LANG_c
|
||||
#define _LANG_m2
|
||||
#define _LANG_chill
|
||||
#define _LANG_fortran
|
||||
|
||||
#define MAX_FORTRAN_DIMS 7 /* Maximum number of F77 array dims */
|
||||
|
||||
/* range_mode ==
|
||||
range_mode_auto: range_check set automatically to default of language.
|
||||
|
|
30
gdb/parse.c
30
gdb/parse.c
|
@ -466,7 +466,18 @@ length_of_subexp (expr, endpos)
|
|||
oplen = 3;
|
||||
break;
|
||||
|
||||
case OP_F77_LITERAL_COMPLEX:
|
||||
oplen = 1;
|
||||
args = 2;
|
||||
break;
|
||||
|
||||
case OP_F77_SUBSTR:
|
||||
oplen = 1;
|
||||
args = 2;
|
||||
break;
|
||||
|
||||
case OP_FUNCALL:
|
||||
case OP_F77_UNDETERMINED_ARGLIST:
|
||||
oplen = 3;
|
||||
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
|
||||
break;
|
||||
|
@ -524,7 +535,9 @@ length_of_subexp (expr, endpos)
|
|||
|
||||
/* Modula-2 */
|
||||
case MULTI_SUBSCRIPT:
|
||||
oplen=3;
|
||||
/* Fortran */
|
||||
case MULTI_F77_SUBSCRIPT:
|
||||
oplen = 3;
|
||||
args = 1 + longest_to_int (expr->elts[endpos- 2].longconst);
|
||||
break;
|
||||
|
||||
|
@ -595,7 +608,18 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
|
|||
oplen = 3;
|
||||
break;
|
||||
|
||||
case OP_F77_LITERAL_COMPLEX:
|
||||
oplen = 1;
|
||||
args = 2;
|
||||
break;
|
||||
|
||||
case OP_F77_SUBSTR:
|
||||
oplen = 1;
|
||||
args = 2;
|
||||
break;
|
||||
|
||||
case OP_FUNCALL:
|
||||
case OP_F77_UNDETERMINED_ARGLIST:
|
||||
oplen = 3;
|
||||
args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
|
||||
break;
|
||||
|
@ -657,7 +681,9 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
|
|||
|
||||
/* Modula-2 */
|
||||
case MULTI_SUBSCRIPT:
|
||||
oplen=3;
|
||||
/* Fortran */
|
||||
case MULTI_F77_SUBSCRIPT:
|
||||
oplen = 3;
|
||||
args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
|
||||
break;
|
||||
|
||||
|
|
467
gdb/valops.c
467
gdb/valops.c
|
@ -33,31 +33,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
/* Local functions. */
|
||||
|
||||
static int
|
||||
typecmp PARAMS ((int staticp, struct type *t1[], value t2[]));
|
||||
static int typecmp PARAMS ((int staticp, struct type *t1[], value_ptr t2[]));
|
||||
|
||||
static CORE_ADDR
|
||||
find_function_addr PARAMS ((value, struct type **));
|
||||
static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **));
|
||||
|
||||
static CORE_ADDR
|
||||
value_push PARAMS ((CORE_ADDR, value));
|
||||
static CORE_ADDR value_push PARAMS ((CORE_ADDR, value_ptr));
|
||||
|
||||
static CORE_ADDR
|
||||
value_arg_push PARAMS ((CORE_ADDR, value));
|
||||
static CORE_ADDR value_arg_push PARAMS ((CORE_ADDR, value_ptr));
|
||||
|
||||
static value
|
||||
search_struct_field PARAMS ((char *, value, int, struct type *, int));
|
||||
static value_ptr search_struct_field PARAMS ((char *, value_ptr, int,
|
||||
struct type *, int));
|
||||
|
||||
static value
|
||||
search_struct_method PARAMS ((char *, value *, value *, int, int *,
|
||||
struct type *));
|
||||
static value_ptr search_struct_method PARAMS ((char *, value_ptr *,
|
||||
value_ptr *,
|
||||
int, int *, struct type *));
|
||||
|
||||
static int
|
||||
check_field_in PARAMS ((struct type *, const char *));
|
||||
|
||||
static CORE_ADDR
|
||||
allocate_space_in_inferior PARAMS ((int));
|
||||
static int check_field_in PARAMS ((struct type *, const char *));
|
||||
|
||||
static CORE_ADDR allocate_space_in_inferior PARAMS ((int));
|
||||
|
||||
/* Allocate NBYTES of space in the inferior using the inferior's malloc
|
||||
and return a value that is a pointer to the allocated space. */
|
||||
|
@ -66,11 +59,11 @@ static CORE_ADDR
|
|||
allocate_space_in_inferior (len)
|
||||
int len;
|
||||
{
|
||||
register value val;
|
||||
register value_ptr val;
|
||||
register struct symbol *sym;
|
||||
struct minimal_symbol *msymbol;
|
||||
struct type *type;
|
||||
value blocklen;
|
||||
value_ptr blocklen;
|
||||
LONGEST maddr;
|
||||
|
||||
/* Find the address of malloc in the inferior. */
|
||||
|
@ -115,10 +108,10 @@ allocate_space_in_inferior (len)
|
|||
and if ARG2 is an lvalue it can be cast into anything at all. */
|
||||
/* In C++, casts may change pointer or object representations. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_cast (type, arg2)
|
||||
struct type *type;
|
||||
register value arg2;
|
||||
register value_ptr arg2;
|
||||
{
|
||||
register enum type_code code1;
|
||||
register enum type_code code2;
|
||||
|
@ -141,8 +134,8 @@ value_cast (type, arg2)
|
|||
/* Look in the type of the source to see if it contains the
|
||||
type of the target as a superclass. If so, we'll need to
|
||||
offset the object in addition to changing its type. */
|
||||
value v = search_struct_field (type_name_no_tag (type),
|
||||
arg2, 0, VALUE_TYPE (arg2), 1);
|
||||
value_ptr v = search_struct_field (type_name_no_tag (type),
|
||||
arg2, 0, VALUE_TYPE (arg2), 1);
|
||||
if (v)
|
||||
{
|
||||
VALUE_TYPE (v) = type;
|
||||
|
@ -167,8 +160,8 @@ value_cast (type, arg2)
|
|||
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT
|
||||
&& TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */
|
||||
{
|
||||
value v = search_struct_field (type_name_no_tag (t1),
|
||||
value_ind (arg2), 0, t2, 1);
|
||||
value_ptr v = search_struct_field (type_name_no_tag (t1),
|
||||
value_ind (arg2), 0, t2, 1);
|
||||
if (v)
|
||||
{
|
||||
v = value_addr (v);
|
||||
|
@ -198,12 +191,12 @@ value_cast (type, arg2)
|
|||
|
||||
/* Create a value of type TYPE that is zero, and return it. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_zero (type, lv)
|
||||
struct type *type;
|
||||
enum lval_type lv;
|
||||
{
|
||||
register value val = allocate_value (type);
|
||||
register value_ptr val = allocate_value (type);
|
||||
|
||||
memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (type));
|
||||
VALUE_LVAL (val) = lv;
|
||||
|
@ -220,12 +213,17 @@ value_zero (type, lv)
|
|||
is tested in the VALUE_CONTENTS macro, which is used if and when
|
||||
the contents are actually required. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_at (type, addr)
|
||||
struct type *type;
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
register value val = allocate_value (type);
|
||||
register value_ptr val;
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_VOID)
|
||||
error ("Attempt to dereference a generic pointer.");
|
||||
|
||||
val = allocate_value (type);
|
||||
|
||||
read_memory (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type));
|
||||
|
||||
|
@ -237,12 +235,17 @@ value_at (type, addr)
|
|||
|
||||
/* Return a lazy value with type TYPE located at ADDR (cf. value_at). */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_at_lazy (type, addr)
|
||||
struct type *type;
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
register value val = allocate_value (type);
|
||||
register value_ptr val;
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_VOID)
|
||||
error ("Attempt to dereference a generic pointer.");
|
||||
|
||||
val = allocate_value (type);
|
||||
|
||||
VALUE_LVAL (val) = lval_memory;
|
||||
VALUE_ADDRESS (val) = addr;
|
||||
|
@ -265,7 +268,7 @@ value_at_lazy (type, addr)
|
|||
|
||||
int
|
||||
value_fetch_lazy (val)
|
||||
register value val;
|
||||
register value_ptr val;
|
||||
{
|
||||
CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val);
|
||||
|
||||
|
@ -280,12 +283,12 @@ value_fetch_lazy (val)
|
|||
/* Store the contents of FROMVAL into the location of TOVAL.
|
||||
Return a new value with the location of TOVAL and contents of FROMVAL. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_assign (toval, fromval)
|
||||
register value toval, fromval;
|
||||
register value_ptr toval, fromval;
|
||||
{
|
||||
register struct type *type;
|
||||
register value val;
|
||||
register value_ptr val;
|
||||
char raw_buffer[MAX_REGISTER_RAW_SIZE];
|
||||
int use_buffer = 0;
|
||||
|
||||
|
@ -514,12 +517,12 @@ Can't handle bitfield which doesn't fit in a single register.");
|
|||
|
||||
/* Extend a value VAL to COUNT repetitions of its type. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_repeat (arg1, count)
|
||||
value arg1;
|
||||
value_ptr arg1;
|
||||
int count;
|
||||
{
|
||||
register value val;
|
||||
register value_ptr val;
|
||||
|
||||
if (VALUE_LVAL (arg1) != lval_memory)
|
||||
error ("Only values in memory can be extended with '@'.");
|
||||
|
@ -537,12 +540,12 @@ value_repeat (arg1, count)
|
|||
return val;
|
||||
}
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_of_variable (var, b)
|
||||
struct symbol *var;
|
||||
struct block *b;
|
||||
{
|
||||
value val;
|
||||
value_ptr val;
|
||||
FRAME fr;
|
||||
|
||||
if (b == NULL)
|
||||
|
@ -590,9 +593,9 @@ value_of_variable (var, b)
|
|||
the coercion to pointer type.
|
||||
*/
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_coerce_array (arg1)
|
||||
value arg1;
|
||||
value_ptr arg1;
|
||||
{
|
||||
register struct type *type;
|
||||
|
||||
|
@ -615,9 +618,9 @@ value_coerce_array (arg1)
|
|||
/* Given a value which is a function, return a value which is a pointer
|
||||
to it. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_coerce_function (arg1)
|
||||
value arg1;
|
||||
value_ptr arg1;
|
||||
{
|
||||
|
||||
if (VALUE_LVAL (arg1) != lval_memory)
|
||||
|
@ -629,9 +632,9 @@ value_coerce_function (arg1)
|
|||
|
||||
/* Return a pointer value for the object for which ARG1 is the contents. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_addr (arg1)
|
||||
value arg1;
|
||||
value_ptr arg1;
|
||||
{
|
||||
struct type *type = VALUE_TYPE (arg1);
|
||||
if (TYPE_CODE (type) == TYPE_CODE_REF)
|
||||
|
@ -639,7 +642,7 @@ value_addr (arg1)
|
|||
/* Copy the value, but change the type from (T&) to (T*).
|
||||
We keep the same location information, which is efficient,
|
||||
and allows &(&X) to get the location containing the reference. */
|
||||
value arg2 = value_copy (arg1);
|
||||
value_ptr arg2 = value_copy (arg1);
|
||||
VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type));
|
||||
return arg2;
|
||||
}
|
||||
|
@ -658,9 +661,9 @@ value_addr (arg1)
|
|||
|
||||
/* Given a value of a pointer type, apply the C unary * operator to it. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_ind (arg1)
|
||||
value arg1;
|
||||
value_ptr arg1;
|
||||
{
|
||||
COERCE_ARRAY (arg1);
|
||||
|
||||
|
@ -729,7 +732,7 @@ push_bytes (sp, buffer, len)
|
|||
static CORE_ADDR
|
||||
value_push (sp, arg)
|
||||
register CORE_ADDR sp;
|
||||
value arg;
|
||||
value_ptr arg;
|
||||
{
|
||||
register int len = TYPE_LENGTH (VALUE_TYPE (arg));
|
||||
|
||||
|
@ -747,9 +750,9 @@ value_push (sp, arg)
|
|||
/* Perform the standard coercions that are specified
|
||||
for arguments to be passed to C functions. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_arg_coerce (arg)
|
||||
value arg;
|
||||
value_ptr arg;
|
||||
{
|
||||
register struct type *type;
|
||||
|
||||
|
@ -789,7 +792,7 @@ value_arg_coerce (arg)
|
|||
static CORE_ADDR
|
||||
value_arg_push (sp, arg)
|
||||
register CORE_ADDR sp;
|
||||
value arg;
|
||||
value_ptr arg;
|
||||
{
|
||||
return value_push (sp, value_arg_coerce (arg));
|
||||
}
|
||||
|
@ -799,7 +802,7 @@ value_arg_push (sp, arg)
|
|||
|
||||
static CORE_ADDR
|
||||
find_function_addr (function, retval_type)
|
||||
value function;
|
||||
value_ptr function;
|
||||
struct type **retval_type;
|
||||
{
|
||||
register struct type *ftype = VALUE_TYPE (function);
|
||||
|
@ -861,11 +864,11 @@ find_function_addr (function, retval_type)
|
|||
May fail to return, if a breakpoint or signal is hit
|
||||
during the execution of the function. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
call_function_by_hand (function, nargs, args)
|
||||
value function;
|
||||
value_ptr function;
|
||||
int nargs;
|
||||
value *args;
|
||||
value_ptr *args;
|
||||
{
|
||||
register CORE_ADDR sp;
|
||||
register int i;
|
||||
|
@ -1018,30 +1021,30 @@ call_function_by_hand (function, nargs, args)
|
|||
|
||||
#if defined (REG_STRUCT_HAS_ADDR)
|
||||
{
|
||||
/* This is a machine like the sparc, where we need to pass a pointer
|
||||
/* This is a machine like the sparc, where we may need to pass a pointer
|
||||
to the structure, not the structure itself. */
|
||||
if (REG_STRUCT_HAS_ADDR (using_gcc))
|
||||
for (i = nargs - 1; i >= 0; i--)
|
||||
if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
for (i = nargs - 1; i >= 0; i--)
|
||||
if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT
|
||||
&& REG_STRUCT_HAS_ADDR (using_gcc, VALUE_TYPE (args[i])))
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
#if !(1 INNER_THAN 2)
|
||||
/* The stack grows up, so the address of the thing we push
|
||||
is the stack pointer before we push it. */
|
||||
addr = sp;
|
||||
/* The stack grows up, so the address of the thing we push
|
||||
is the stack pointer before we push it. */
|
||||
addr = sp;
|
||||
#endif
|
||||
/* Push the structure. */
|
||||
sp = value_push (sp, args[i]);
|
||||
/* Push the structure. */
|
||||
sp = value_push (sp, args[i]);
|
||||
#if 1 INNER_THAN 2
|
||||
/* The stack grows down, so the address of the thing we push
|
||||
is the stack pointer after we push it. */
|
||||
addr = sp;
|
||||
/* The stack grows down, so the address of the thing we push
|
||||
is the stack pointer after we push it. */
|
||||
addr = sp;
|
||||
#endif
|
||||
/* The value we're going to pass is the address of the thing
|
||||
we just pushed. */
|
||||
args[i] = value_from_longest (lookup_pointer_type (value_type),
|
||||
(LONGEST) addr);
|
||||
}
|
||||
/* The value we're going to pass is the address of the thing
|
||||
we just pushed. */
|
||||
args[i] = value_from_longest (lookup_pointer_type (value_type),
|
||||
(LONGEST) addr);
|
||||
}
|
||||
}
|
||||
#endif /* REG_STRUCT_HAS_ADDR. */
|
||||
|
||||
|
@ -1146,11 +1149,11 @@ the function call).", name);
|
|||
}
|
||||
}
|
||||
#else /* no CALL_DUMMY. */
|
||||
value
|
||||
value_ptr
|
||||
call_function_by_hand (function, nargs, args)
|
||||
value function;
|
||||
value_ptr function;
|
||||
int nargs;
|
||||
value *args;
|
||||
value_ptr *args;
|
||||
{
|
||||
error ("Cannot invoke functions on this machine.");
|
||||
}
|
||||
|
@ -1167,16 +1170,16 @@ call_function_by_hand (function, nargs, args)
|
|||
first element, and all elements must have the same size (though we
|
||||
don't currently enforce any restriction on their types). */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_array (lowbound, highbound, elemvec)
|
||||
int lowbound;
|
||||
int highbound;
|
||||
value *elemvec;
|
||||
value_ptr *elemvec;
|
||||
{
|
||||
int nelem;
|
||||
int idx;
|
||||
int typelength;
|
||||
value val;
|
||||
value_ptr val;
|
||||
struct type *rangetype;
|
||||
struct type *arraytype;
|
||||
CORE_ADDR addr;
|
||||
|
@ -1228,12 +1231,12 @@ value_array (lowbound, highbound, elemvec)
|
|||
zero and an upper bound of LEN - 1. Also note that the string may contain
|
||||
embedded null bytes. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_string (ptr, len)
|
||||
char *ptr;
|
||||
int len;
|
||||
{
|
||||
value val;
|
||||
value_ptr val;
|
||||
struct type *rangetype;
|
||||
struct type *stringtype;
|
||||
CORE_ADDR addr;
|
||||
|
@ -1273,7 +1276,7 @@ static int
|
|||
typecmp (staticp, t1, t2)
|
||||
int staticp;
|
||||
struct type *t1[];
|
||||
value t2[];
|
||||
value_ptr t2[];
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1327,10 +1330,10 @@ typecmp (staticp, t1, t2)
|
|||
If LOOKING_FOR_BASECLASS, then instead of looking for struct fields,
|
||||
look for a baseclass named NAME. */
|
||||
|
||||
static value
|
||||
static value_ptr
|
||||
search_struct_field (name, arg1, offset, type, looking_for_baseclass)
|
||||
char *name;
|
||||
register value arg1;
|
||||
register value_ptr arg1;
|
||||
int offset;
|
||||
register struct type *type;
|
||||
int looking_for_baseclass;
|
||||
|
@ -1346,7 +1349,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
|
|||
|
||||
if (t_field_name && STREQ (t_field_name, name))
|
||||
{
|
||||
value v;
|
||||
value_ptr v;
|
||||
if (TYPE_FIELD_STATIC (type, i))
|
||||
{
|
||||
char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i);
|
||||
|
@ -1368,7 +1371,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
|
|||
|
||||
for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
|
||||
{
|
||||
value v;
|
||||
value_ptr v;
|
||||
/* If we are looking for baseclasses, this is what we get when we
|
||||
hit them. But it could happen that the base part's member name
|
||||
is not yet filled in. */
|
||||
|
@ -1378,7 +1381,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
|
|||
|
||||
if (BASETYPE_VIA_VIRTUAL (type, i))
|
||||
{
|
||||
value v2;
|
||||
value_ptr v2;
|
||||
/* Fix to use baseclass_offset instead. FIXME */
|
||||
baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset,
|
||||
&v2, (int *)NULL);
|
||||
|
@ -1407,15 +1410,15 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
|
|||
If found, return value, else if name matched and args not return (value)-1,
|
||||
else return NULL. */
|
||||
|
||||
static value
|
||||
static value_ptr
|
||||
search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
|
||||
char *name;
|
||||
register value *arg1p, *args;
|
||||
register value_ptr *arg1p, *args;
|
||||
int offset, *static_memfuncp;
|
||||
register struct type *type;
|
||||
{
|
||||
int i;
|
||||
value v;
|
||||
value_ptr v;
|
||||
int name_matched = 0;
|
||||
char dem_opname[64];
|
||||
|
||||
|
@ -1448,11 +1451,11 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
|
|||
TYPE_FN_FIELD_ARGS (f, j), args))
|
||||
{
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
|
||||
return (value)value_virtual_fn_field (arg1p, f, j, type, offset);
|
||||
return value_virtual_fn_field (arg1p, f, j, type, offset);
|
||||
if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
|
||||
*static_memfuncp = 1;
|
||||
v = (value)value_fn_field (arg1p, f, j, type, offset);
|
||||
if (v != (value)NULL) return v;
|
||||
v = value_fn_field (arg1p, f, j, type, offset);
|
||||
if (v != NULL) return v;
|
||||
}
|
||||
j--;
|
||||
}
|
||||
|
@ -1475,7 +1478,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
|
|||
}
|
||||
v = search_struct_method (name, arg1p, args, base_offset + offset,
|
||||
static_memfuncp, TYPE_BASECLASS (type, i));
|
||||
if (v == (value) -1)
|
||||
if (v == (value_ptr) -1)
|
||||
{
|
||||
name_matched = 1;
|
||||
}
|
||||
|
@ -1486,7 +1489,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
|
|||
return v;
|
||||
}
|
||||
}
|
||||
if (name_matched) return (value) -1;
|
||||
if (name_matched) return (value_ptr) -1;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
|
@ -1504,15 +1507,15 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
|
|||
|
||||
ERR is an error message to be printed in case the field is not found. */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_struct_elt (argp, args, name, static_memfuncp, err)
|
||||
register value *argp, *args;
|
||||
register value_ptr *argp, *args;
|
||||
char *name;
|
||||
int *static_memfuncp;
|
||||
char *err;
|
||||
{
|
||||
register struct type *t;
|
||||
value v;
|
||||
value_ptr v;
|
||||
|
||||
COERCE_ARRAY (*argp);
|
||||
|
||||
|
@ -1558,7 +1561,7 @@ value_struct_elt (argp, args, name, static_memfuncp, err)
|
|||
|
||||
v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
|
||||
|
||||
if (v == (value) -1)
|
||||
if (v == (value_ptr) -1)
|
||||
error ("Cannot take address of a method");
|
||||
else if (v == 0)
|
||||
{
|
||||
|
@ -1575,8 +1578,8 @@ value_struct_elt (argp, args, name, static_memfuncp, err)
|
|||
if (!args[1])
|
||||
{
|
||||
/* destructors are a special case. */
|
||||
v = (value)value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, 0),
|
||||
TYPE_FN_FIELDLIST_LENGTH (t, 0), 0, 0);
|
||||
v = value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, 0),
|
||||
TYPE_FN_FIELDLIST_LENGTH (t, 0), 0, 0);
|
||||
if (!v) error("could not find destructor function named %s.", name);
|
||||
else return v;
|
||||
}
|
||||
|
@ -1588,7 +1591,7 @@ value_struct_elt (argp, args, name, static_memfuncp, err)
|
|||
else
|
||||
v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
|
||||
|
||||
if (v == (value) -1)
|
||||
if (v == (value_ptr) -1)
|
||||
{
|
||||
error("Argument list of %s mismatch with component in the structure.", name);
|
||||
}
|
||||
|
@ -1671,7 +1674,7 @@ check_field_in (type, name)
|
|||
|
||||
int
|
||||
check_field (arg1, name)
|
||||
register value arg1;
|
||||
register value_ptr arg1;
|
||||
const char *name;
|
||||
{
|
||||
register struct type *t;
|
||||
|
@ -1702,7 +1705,7 @@ check_field (arg1, name)
|
|||
"pointers to member functions". This function is used
|
||||
to resolve user expressions of the form "DOMAIN::NAME". */
|
||||
|
||||
value
|
||||
value_ptr
|
||||
value_struct_elt_for_reference (domain, offset, curtype, name, intype)
|
||||
struct type *domain, *curtype, *intype;
|
||||
int offset;
|
||||
|
@ -1710,7 +1713,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype)
|
|||
{
|
||||
register struct type *t = curtype;
|
||||
register int i;
|
||||
value v;
|
||||
value_ptr v;
|
||||
|
||||
if ( TYPE_CODE (t) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
|
@ -1822,7 +1825,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype)
|
|||
}
|
||||
for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
|
||||
{
|
||||
value v;
|
||||
value_ptr v;
|
||||
int base_offset;
|
||||
|
||||
if (BASETYPE_VIA_VIRTUAL (t, i))
|
||||
|
@ -1843,7 +1846,7 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype)
|
|||
/* C++: return the value of the class instance variable, if one exists.
|
||||
Flag COMPLAIN signals an error if the request is made in an
|
||||
inappropriate context. */
|
||||
value
|
||||
value_ptr
|
||||
value_of_this (complain)
|
||||
int complain;
|
||||
{
|
||||
|
@ -1852,7 +1855,7 @@ value_of_this (complain)
|
|||
struct block *b;
|
||||
int i;
|
||||
static const char funny_this[] = "this";
|
||||
value this;
|
||||
value_ptr this;
|
||||
|
||||
if (selected_frame == 0)
|
||||
if (complain)
|
||||
|
@ -1890,3 +1893,243 @@ value_of_this (complain)
|
|||
error ("`this' argument at unknown address");
|
||||
return this;
|
||||
}
|
||||
|
||||
/* Create a value for a literal string. We copy data into a local
|
||||
(NOT inferior's memory) buffer, and then set up an array value.
|
||||
|
||||
The array bounds are set from LOWBOUND and HIGHBOUND, and the array is
|
||||
populated from the values passed in ELEMVEC.
|
||||
|
||||
The element type of the array is inherited from the type of the
|
||||
first element, and all elements must have the same size (though we
|
||||
don't currently enforce any restriction on their types). */
|
||||
|
||||
value_ptr
|
||||
f77_value_literal_string (lowbound, highbound, elemvec)
|
||||
int lowbound;
|
||||
int highbound;
|
||||
value_ptr *elemvec;
|
||||
{
|
||||
int nelem;
|
||||
int idx;
|
||||
int typelength;
|
||||
register value_ptr val;
|
||||
struct type *rangetype;
|
||||
struct type *arraytype;
|
||||
CORE_ADDR addr;
|
||||
|
||||
/* Validate that the bounds are reasonable and that each of the elements
|
||||
have the same size. */
|
||||
|
||||
nelem = highbound - lowbound + 1;
|
||||
if (nelem <= 0)
|
||||
error ("bad array bounds (%d, %d)", lowbound, highbound);
|
||||
typelength = TYPE_LENGTH (VALUE_TYPE (elemvec[0]));
|
||||
for (idx = 0; idx < nelem; idx++)
|
||||
{
|
||||
if (TYPE_LENGTH (VALUE_TYPE (elemvec[idx])) != typelength)
|
||||
error ("array elements must all be the same size");
|
||||
}
|
||||
|
||||
/* Make sure we are dealing with characters */
|
||||
|
||||
if (typelength != 1)
|
||||
error ("Found a non character type in a literal string ");
|
||||
|
||||
/* Allocate space to store the array */
|
||||
|
||||
addr = malloc (nelem);
|
||||
for (idx = 0; idx < nelem; idx++)
|
||||
{
|
||||
memcpy (addr + (idx), VALUE_CONTENTS (elemvec[idx]), 1);
|
||||
}
|
||||
|
||||
rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
|
||||
lowbound, highbound);
|
||||
|
||||
arraytype = f77_create_literal_string_type ((struct type *) NULL,
|
||||
rangetype);
|
||||
|
||||
val = allocate_value (arraytype);
|
||||
|
||||
/* Make sure that this the rest of the world knows that this is
|
||||
a standard literal string, not one that is a substring of
|
||||
some base */
|
||||
|
||||
VALUE_SUBSTRING_START (val) = NULL;
|
||||
|
||||
VALUE_LAZY (val) = 0;
|
||||
VALUE_LITERAL_DATA (val) = addr;
|
||||
|
||||
/* Since this is a standard literal string with no real lval,
|
||||
make sure that value_lval indicates this fact */
|
||||
|
||||
VALUE_LVAL (val) = not_lval;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Create a value for a substring. We copy data into a local
|
||||
(NOT inferior's memory) buffer, and then set up an array value.
|
||||
|
||||
The array bounds for the string are (1:(to-from +1))
|
||||
The elements of the string are all characters. */
|
||||
|
||||
value_ptr
|
||||
f77_value_substring (str, from, to)
|
||||
value_ptr str;
|
||||
int from;
|
||||
int to;
|
||||
{
|
||||
int nelem;
|
||||
register value_ptr val;
|
||||
struct type *rangetype;
|
||||
struct type *arraytype;
|
||||
struct internalvar *var;
|
||||
CORE_ADDR addr;
|
||||
|
||||
/* Validate that the bounds are reasonable. */
|
||||
|
||||
nelem = to - from + 1;
|
||||
if (nelem <= 0)
|
||||
error ("bad substring bounds (%d, %d)", from, to);
|
||||
|
||||
rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
|
||||
1, nelem);
|
||||
|
||||
arraytype = f77_create_literal_string_type ((struct type *) NULL,
|
||||
rangetype);
|
||||
|
||||
val = allocate_value (arraytype);
|
||||
|
||||
/* Allocate space to store the substring array */
|
||||
|
||||
addr = malloc (nelem);
|
||||
|
||||
/* Copy over the data */
|
||||
|
||||
/* In case we ever try to use this substring on the LHS of an assignment
|
||||
remember where the SOURCE substring begins, for lval_memory
|
||||
types this ptr is to a location in legal inferior memory,
|
||||
for lval_internalvars it is a ptr. to superior memory. This
|
||||
helps us out later when we do assigments like:
|
||||
|
||||
set var ARR(2:3) = 'ab'
|
||||
|
||||
*/
|
||||
|
||||
|
||||
if (VALUE_LVAL (str) == lval_memory)
|
||||
{
|
||||
if (VALUE_SUBSTRING_START (str) == NULL)
|
||||
{
|
||||
/* This is a regular lval_memory string located in the
|
||||
inferior */
|
||||
|
||||
VALUE_SUBSTRING_START (val) = VALUE_ADDRESS (str) + (from - 1);
|
||||
target_read_memory (VALUE_SUBSTRING_START (val), addr, nelem);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#if 0
|
||||
/* str is a substring allocated in the superior. Just
|
||||
do a memcpy */
|
||||
|
||||
VALUE_SUBSTRING_START(val) = VALUE_LITERAL_DATA(str)+(from - 1);
|
||||
memcpy(addr,VALUE_SUBSTRING_START(val),nelem);
|
||||
#else
|
||||
error ("Cannot get substrings of substrings");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
if (VALUE_LVAL(str) == lval_internalvar)
|
||||
{
|
||||
/* Internal variables of type TYPE_CODE_LITERAL_STRING
|
||||
have their data located in the superior
|
||||
process not the inferior */
|
||||
|
||||
var = VALUE_INTERNALVAR (str);
|
||||
|
||||
if (VALUE_SUBSTRING_START (str) == NULL)
|
||||
VALUE_SUBSTRING_START (val) =
|
||||
VALUE_LITERAL_DATA (var->value) + (from - 1);
|
||||
else
|
||||
#if 0
|
||||
VALUE_SUBSTRING_START(val)=VALUE_LITERAL_DATA(str)+(from -1);
|
||||
#else
|
||||
error ("Cannot get substrings of substrings");
|
||||
#endif
|
||||
memcpy (addr, VALUE_SUBSTRING_START (val), nelem);
|
||||
}
|
||||
else
|
||||
error ("Substrings can not be applied to this data item");
|
||||
|
||||
VALUE_LAZY (val) = 0;
|
||||
VALUE_LITERAL_DATA (val) = addr;
|
||||
|
||||
/* This literal string's *data* is located in the superior BUT
|
||||
we do need to know where it came from (i.e. was the source
|
||||
string an internalvar or a regular lval_memory variable), so
|
||||
we set the lval field to indicate this. This will be useful
|
||||
when we use this value on the LHS of an expr. */
|
||||
|
||||
VALUE_LVAL (val) = VALUE_LVAL (str);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Create a value for a FORTRAN complex number. Currently most of
|
||||
the time values are coerced to COMPLEX*16 (i.e. a complex number
|
||||
composed of 2 doubles. This really should be a smarter routine
|
||||
that figures out precision inteligently as opposed to assuming
|
||||
doubles. FIXME: fmb */
|
||||
|
||||
value_ptr
|
||||
f77_value_literal_complex (arg1, arg2, size)
|
||||
value_ptr arg1;
|
||||
value_ptr arg2;
|
||||
int size;
|
||||
{
|
||||
struct type *complex_type;
|
||||
register value_ptr val;
|
||||
char *addr;
|
||||
|
||||
if (size != 8 && size != 16 && size != 32)
|
||||
error ("Cannot create number of type 'complex*%d'", size);
|
||||
|
||||
/* If either value comprising a complex number is a non-floating
|
||||
type, cast to double. */
|
||||
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT)
|
||||
arg1 = value_cast (builtin_type_f_real_s8, arg1);
|
||||
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT)
|
||||
arg2 = value_cast (builtin_type_f_real_s8, arg2);
|
||||
|
||||
complex_type = f77_create_literal_complex_type (VALUE_TYPE (arg1),
|
||||
VALUE_TYPE (arg2),
|
||||
size);
|
||||
|
||||
val = allocate_value (complex_type);
|
||||
|
||||
/* Now create a pointer to enough memory to hold the the two args */
|
||||
|
||||
addr = malloc (TYPE_LENGTH (complex_type));
|
||||
|
||||
/* Copy over the two components */
|
||||
|
||||
memcpy (addr, VALUE_CONTENTS_RAW (arg1), TYPE_LENGTH (VALUE_TYPE (arg1)));
|
||||
|
||||
memcpy (addr + TYPE_LENGTH (VALUE_TYPE (arg1)), VALUE_CONTENTS_RAW (arg2),
|
||||
TYPE_LENGTH (VALUE_TYPE (arg2)));
|
||||
|
||||
VALUE_ADDRESS (val) = 0; /* Not located in the inferior */
|
||||
VALUE_LAZY (val) = 0;
|
||||
VALUE_LITERAL_DATA (val) = addr;
|
||||
|
||||
/* Since this is a literal value, make sure that value_lval indicates
|
||||
this fact */
|
||||
|
||||
VALUE_LVAL (val) = not_lval;
|
||||
return val;
|
||||
}
|
||||
|
|
32
gdb/value.h
32
gdb/value.h
|
@ -139,6 +139,28 @@ extern int value_fetch_lazy PARAMS ((value_ptr val));
|
|||
#define VALUE_REGNO(val) (val)->regno
|
||||
#define VALUE_OPTIMIZED_OUT(val) ((val)->optimized_out)
|
||||
|
||||
/* This is probably not the right thing to do for in-gdb arrays. FIXME */
|
||||
/* Overload the contents field to store literal data for
|
||||
arrays. */
|
||||
|
||||
#define VALUE_LITERAL_DATA(val) ((val)->aligner.contents[0])
|
||||
|
||||
/* Overload the frame address field to contain a pointer to
|
||||
the base substring, for F77 string substring operators.
|
||||
We use this ONLY when doing operations of the form
|
||||
|
||||
FOO= 'hello'
|
||||
FOO(2:4) = 'foo'
|
||||
|
||||
In the above case VALUE_SUBSTRING_START would point to
|
||||
FOO(2) in the original FOO string.
|
||||
|
||||
Depending on whether the base object is allocated in the
|
||||
inferior or the superior process, VALUE_SUBSTRING_START
|
||||
contains a ptr. to memory in the relevant area. */
|
||||
|
||||
#define VALUE_SUBSTRING_START(val) VALUE_FRAME(val)
|
||||
|
||||
/* Convert a REF to the object referenced. */
|
||||
|
||||
#define COERCE_REF(arg) \
|
||||
|
@ -433,6 +455,10 @@ print_floating PARAMS ((char *valaddr, struct type *type, GDB_FILE *stream));
|
|||
extern int value_print PARAMS ((value_ptr val, GDB_FILE *stream, int format,
|
||||
enum val_prettyprint pretty));
|
||||
|
||||
extern void
|
||||
value_print_array_elements PARAMS ((value_ptr val, GDB_FILE* stream,
|
||||
int format, enum val_prettyprint pretty));
|
||||
|
||||
extern value_ptr
|
||||
value_release_to_mark PARAMS ((value_ptr mark));
|
||||
|
||||
|
@ -475,4 +501,10 @@ extern int baseclass_offset PARAMS ((struct type *, int, value_ptr, int));
|
|||
|
||||
extern value_ptr call_function_by_hand PARAMS ((value_ptr, int, value_ptr *));
|
||||
|
||||
extern value_ptr f77_value_literal_complex PARAMS ((value_ptr, value_ptr, int));
|
||||
|
||||
extern value_ptr f77_value_literal_string PARAMS ((int, int, value_ptr *));
|
||||
|
||||
extern value_ptr f77_value_substring PARAMS ((value_ptr, int, int));
|
||||
|
||||
#endif /* !defined (VALUE_H) */
|
||||
|
|
Loading…
Reference in a new issue