aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>1994-08-19 21:59:05 +0000
committerStan Shebs <shebs@codesourcery.com>1994-08-19 21:59:05 +0000
commita91a61923d82c39ebeb9971635b76c7da494cab4 (patch)
tree5d26199b5455ca2369b432d008da29521e861908
parentf3806e3b6ceead276a3acba85ff944fde6668e39 (diff)
downloadfsf-binutils-gdb-a91a61923d82c39ebeb9971635b76c7da494cab4.zip
fsf-binutils-gdb-a91a61923d82c39ebeb9971635b76c7da494cab4.tar.gz
fsf-binutils-gdb-a91a61923d82c39ebeb9971635b76c7da494cab4.tar.bz2
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.
-rw-r--r--gdb/ChangeLog37
-rw-r--r--gdb/f-exp.y1246
-rw-r--r--gdb/f-lang.c945
-rw-r--r--gdb/f-lang.h90
-rw-r--r--gdb/f-typeprint.c457
-rw-r--r--gdb/f-valprint.c889
-rw-r--r--gdb/gdbtypes.c80
-rw-r--r--gdb/gdbtypes.h50
-rw-r--r--gdb/language.c1
-rw-r--r--gdb/language.h3
-rw-r--r--gdb/parse.c30
-rw-r--r--gdb/valops.c467
-rw-r--r--gdb/value.h32
13 files changed, 4209 insertions, 118 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fcdd266..a7cc010 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
new file mode 100644
index 0000000..27eda23
--- /dev/null
+++ b/gdb/f-exp.y
@@ -0,0 +1,1246 @@
+/* YACC parser for Fortran expressions, for GDB.
+ Copyright 1986, 1989, 1990, 1991, 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. */
+
+/* This was blantantly ripped off the C expression parser, please
+ be aware of that as you look at its basic structure -FMB */
+
+/* Parse a F77 expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator. */
+
+%{
+
+#include "defs.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "value.h"
+#include "language.h"
+#include "f-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth f_maxdepth
+#define yyparse f_parse
+#define yylex f_lex
+#define yyerror f_error
+#define yylval f_lval
+#define yychar f_char
+#define yydebug f_debug
+#define yypact f_pact
+#define yyr1 f_r1
+#define yyr2 f_r2
+#define yydef f_def
+#define yychk f_chk
+#define yypgo f_pgo
+#define yyact f_act
+#define yyexca f_exca
+#define yyerrflag f_errflag
+#define yynerrs f_nerrs
+#define yyps f_ps
+#define yypv f_pv
+#define yys f_s
+#define yy_yys f_yys
+#define yystate f_state
+#define yytmp f_tmp
+#define yyv f_v
+#define yy_yyv f_yyv
+#define yyval f_val
+#define yylloc f_lloc
+#define yyreds f_reds /* With YYDEBUG defined */
+#define yytoks f_toks /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define YYDEBUG 1 /* Default to no yydebug support */
+#endif
+
+int yyparse PARAMS ((void));
+
+static int yylex PARAMS ((void));
+
+void yyerror PARAMS ((char *));
+
+%}
+
+/* Although the yacc "value" of an expression is not used,
+ since the result is stored in the structure being created,
+ other node types do have values. */
+
+%union
+ {
+ LONGEST lval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
+ double dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%{
+/* YYSTYPE gets defined by %union */
+static int parse_number PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%type <voidval> exp type_exp start variable
+%type <tval> type typebase
+%type <tvec> nonempty_typelist
+/* %type <bval> block */
+
+/* Fancy type parsing. */
+%type <voidval> func_mod direct_abs_decl abs_decl
+%type <tval> ptype
+
+%token <typed_val> INT
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+ and both convey their data as strings.
+ But a TYPENAME is a string that happens to be defined as a typedef
+ or builtin type name (such as int or char)
+ and a NAME is any other symbol.
+ Contexts where this distinction is not important can use the
+ nonterminal "name", which matches either NAME or TYPENAME. */
+
+%token <sval> STRING_LITERAL
+%token <lval> BOOLEAN_LITERAL
+%token <ssym> NAME
+%token <tsym> TYPENAME
+%type <sval> name
+%type <ssym> name_not_typename
+%type <tsym> typename
+
+/* A NAME_OR_INT is a symbol which is not known in the symbol table,
+ but which would parse as a valid number in the current input radix.
+ E.g. "c" when input_radix==16. Depending on the parse, it will be
+ turned into a name or into a number. */
+
+%token <ssym> NAME_OR_INT
+
+%token SIZEOF
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token INT_KEYWORD INT_S2_KEYWORD LOGICAL_S1_KEYWORD LOGICAL_S2_KEYWORD
+%token LOGICAL_KEYWORD REAL_KEYWORD REAL_S8_KEYWORD REAL_S16_KEYWORD
+%token COMPLEX_S8_KEYWORD COMPLEX_S16_KEYWORD COMPLEX_S32_KEYWORD
+%token BOOL_AND BOOL_OR BOOL_NOT
+%token <lval> LAST REGNAME CHARACTER
+
+%token <ivar> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left BOOL_OR
+%right BOOL_NOT
+%left BOOL_AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left LESSTHAN GREATERTHAN LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+%right '('
+
+
+%%
+
+start : exp
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE); }
+ ;
+
+
+exp : '(' exp ')'
+ { }
+ ;
+
+/* Expressions, not including the comma operator. */
+exp : '*' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '&' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ADDR); }
+
+exp : '-' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : BOOL_NOT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+ ;
+
+exp : SIZEOF exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+/* No more explicit array operators, we treat everything in F77 as
+ a function call. The disambiguation as to whether we are
+ doing a subscript operation or a function call is done
+ later in eval.c. */
+
+exp : exp '('
+ { start_arglist (); }
+ arglist ')'
+ { write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : substring
+ { arglist_len = 2;}
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+substring: exp ':' exp %prec ABOVE_COMMA
+ { }
+ ;
+
+
+complexnum: exp ',' exp
+ { }
+ ;
+
+exp : '(' complexnum ')'
+ { write_exp_elt_opcode(OP_F77_LITERAL_COMPLEX); }
+ ;
+
+exp : '(' type ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+/* Binary operators in order of decreasing precedence. */
+
+exp : exp '@' exp
+ { write_exp_elt_opcode (BINOP_REPEAT); }
+ ;
+
+exp : exp '*' exp
+ { write_exp_elt_opcode (BINOP_MUL); }
+ ;
+
+exp : exp '/' exp
+ { write_exp_elt_opcode (BINOP_DIV); }
+ ;
+
+exp : exp '%' exp
+ { write_exp_elt_opcode (BINOP_REM); }
+ ;
+
+exp : exp '+' exp
+ { write_exp_elt_opcode (BINOP_ADD); }
+ ;
+
+exp : exp '-' exp
+ { write_exp_elt_opcode (BINOP_SUB); }
+ ;
+
+exp : exp LSH exp
+ { write_exp_elt_opcode (BINOP_LSH); }
+ ;
+
+exp : exp RSH exp
+ { write_exp_elt_opcode (BINOP_RSH); }
+ ;
+
+exp : exp EQUAL exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ ;
+
+exp : exp LEQ exp
+ { write_exp_elt_opcode (BINOP_LEQ); }
+ ;
+
+exp : exp GEQ exp
+ { write_exp_elt_opcode (BINOP_GEQ); }
+ ;
+
+exp : exp LESSTHAN exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp GREATERTHAN exp
+ { write_exp_elt_opcode (BINOP_GTR); }
+ ;
+
+exp : exp '&' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+ ;
+
+exp : exp '^' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+ ;
+
+exp : exp '|' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+ ;
+
+exp : exp BOOL_AND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+
+exp : exp BOOL_OR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+ ;
+
+exp : exp '=' exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+exp : exp ASSIGN_MODIFY exp
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST)($1.val));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : NAME_OR_INT
+ { YYSTYPE val;
+ parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_f_real_s8);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : LAST
+ { write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LAST); }
+ ;
+
+exp : REGNAME
+ { write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_REGISTER); }
+ ;
+
+exp : VARIABLE
+ { write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern ($1);
+ write_exp_elt_opcode (OP_INTERNALVAR); }
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_f_integer);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : BOOLEAN_LITERAL
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL);
+ }
+ ;
+
+exp : STRING_LITERAL
+ { /* In F77, we encounter string literals
+ basically in only one place:
+ when we are setting up manual parameter
+ lists to functions we call by hand or
+ when setting string vars to manual values.
+ These are character*N type variables.
+ They are treated specially behind the
+ scenes. Remember that the literal strings's
+ OPs are being emitted in reverse order, thus
+ we first have the elements and then
+ the array descriptor itself. */
+ char *sp = $1.ptr; int count = $1.length;
+
+ while (count-- > 0)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_f_character);
+ write_exp_elt_longcst ((LONGEST)(*sp++));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 1);
+ write_exp_elt_longcst ((LONGEST) ($1.length));
+ write_exp_elt_opcode (OP_ARRAY);
+ }
+
+ ;
+
+variable: name_not_typename
+ { struct symbol *sym = $1.sym;
+
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1.stoken);
+
+ msymbol = lookup_minimal_symbol (arg, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+
+type : ptype
+ ;
+
+ptype : typebase
+ | typebase abs_decl
+ {
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = $1;
+ struct type *range_type;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = pop_type_int ();
+ if (array_size != -1)
+ {
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_f_integer, 0,
+ array_size - 1);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ }
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ $$ = follow_type;
+ }
+ ;
+
+abs_decl: '*'
+ { push_type (tp_pointer); $$ = 0; }
+ | '*' abs_decl
+ { push_type (tp_pointer); $$ = $2; }
+ | '&'
+ { push_type (tp_reference); $$ = 0; }
+ | '&' abs_decl
+ { push_type (tp_reference); $$ = $2; }
+ | direct_abs_decl
+ ;
+
+direct_abs_decl: '(' abs_decl ')'
+ { $$ = $2; }
+ | direct_abs_decl func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ | '(' nonempty_typelist ')'
+ { free ((PTR)$2); $$ = 0; }
+ ;
+
+typebase /* Implements (approximately): (type-qualifier)* type-specifier */
+ : TYPENAME
+ { $$ = $1.type; }
+ | INT_KEYWORD
+ { $$ = builtin_type_f_integer; }
+ | INT_S2_KEYWORD
+ { $$ = builtin_type_f_integer_s2; }
+ | CHARACTER
+ { $$ = builtin_type_f_character; }
+ | LOGICAL_KEYWORD
+ { $$ = builtin_type_f_logical;}
+ | LOGICAL_S2_KEYWORD
+ { $$ = builtin_type_f_logical_s2;}
+ | LOGICAL_S1_KEYWORD
+ { $$ = builtin_type_f_logical_s1;}
+ | REAL_KEYWORD
+ { $$ = builtin_type_f_real;}
+ | REAL_S8_KEYWORD
+ { $$ = builtin_type_f_real_s8;}
+ | REAL_S16_KEYWORD
+ { $$ = builtin_type_f_real_s16;}
+ | COMPLEX_S8_KEYWORD
+ { $$ = builtin_type_f_complex_s8;}
+ | COMPLEX_S16_KEYWORD
+ { $$ = builtin_type_f_complex_s16;}
+ | COMPLEX_S32_KEYWORD
+ { $$ = builtin_type_f_complex_s32;}
+ ;
+
+typename: TYPENAME
+ ;
+
+nonempty_typelist
+ : type
+ { $$ = (struct type **) malloc (sizeof (struct type *) * 2);
+ $<ivec>$[0] = 1; /* Number of types in vector */
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+ $$ = (struct type **) realloc ((char *) $1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
+name : NAME
+ { $$ = $1.stoken; }
+ | TYPENAME
+ { $$ = $1.stoken; }
+ | NAME_OR_INT
+ { $$ = $1.stoken; }
+ ;
+
+name_not_typename : NAME
+/* These would be useful if name_not_typename was useful, but it is just
+ a fake for "variable", so these cause reduce/reduce conflicts because
+ the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
+ =exp) or just an exp. If name_not_typename was ever used in an lvalue
+ context where only a name could occur, this might be useful.
+ | NAME_OR_INT
+ */
+ ;
+
+%%
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ register int i;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+ int long_p = 0;
+ unsigned LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ putithere->dval = atof (p);
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += i = c - '0';
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ n += i = c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ long_p = 1;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). */
+ if ((prevn >= n) && n != 0)
+ unsigned_p=1; /* Try something unsigned */
+ /* If range checking enabled, portably test for unsigned overflow. */
+ if (RANGE_CHECK && n != 0)
+ {
+ if ((unsigned_p && (unsigned)prevn >= (unsigned)n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn = n;
+ }
+
+ /* If the number is too big to be an int, or it's got an l suffix
+ then it's a long. Work out if this has to be a long by
+ shifting right and and seeing if anything remains, and the
+ target int size is different to the target long size.
+
+ In the expression below, we could have tested
+ (n >> TARGET_INT_BIT)
+ to see if it was zero,
+ but too many compilers warn about that, when ints and longs
+ are the same size. So we shift it twice, with fewer bits
+ each time, for the same result. */
+
+ if ((TARGET_INT_BIT != TARGET_LONG_BIT
+ && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
+ || long_p)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+
+ putithere->typed_val.val = n;
+
+ /* If the high bit of the worked out type is set then this number
+ has to be unsigned. */
+
+ if (unsigned_p || (n & high_bit))
+ putithere->typed_val.type = unsigned_type;
+ else
+ putithere->typed_val.type = signed_type;
+
+ return INT;
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static const struct token dot_ops[] =
+{
+ { ".and.", BOOL_AND, BINOP_END },
+ { ".AND.", BOOL_AND, BINOP_END },
+ { ".or.", BOOL_OR, BINOP_END },
+ { ".OR.", BOOL_OR, BINOP_END },
+ { ".not.", BOOL_NOT, BINOP_END },
+ { ".NOT.", BOOL_NOT, BINOP_END },
+ { ".eq.", EQUAL, BINOP_END },
+ { ".EQ.", EQUAL, BINOP_END },
+ { ".eqv.", EQUAL, BINOP_END },
+ { ".NEQV.", NOTEQUAL, BINOP_END },
+ { ".neqv.", NOTEQUAL, BINOP_END },
+ { ".EQV.", EQUAL, BINOP_END },
+ { ".ne.", NOTEQUAL, BINOP_END },
+ { ".NE.", NOTEQUAL, BINOP_END },
+ { ".le.", LEQ, BINOP_END },
+ { ".LE.", LEQ, BINOP_END },
+ { ".ge.", GEQ, BINOP_END },
+ { ".GE.", GEQ, BINOP_END },
+ { ".gt.", GREATERTHAN, BINOP_END },
+ { ".GT.", GREATERTHAN, BINOP_END },
+ { ".lt.", LESSTHAN, BINOP_END },
+ { ".LT.", LESSTHAN, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+struct f77_boolean_val
+{
+ char *name;
+ int value;
+};
+
+static const struct f77_boolean_val boolean_values[] =
+{
+ { ".true.", 1 },
+ { ".TRUE.", 1 },
+ { ".false.", 0 },
+ { ".FALSE.", 0 },
+ { NULL, 0 }
+};
+
+static const struct token f77_keywords[] =
+{
+ { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END },
+ { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END },
+ { "character", CHARACTER, BINOP_END },
+ { "integer_2", INT_S2_KEYWORD, BINOP_END },
+ { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END },
+ { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END },
+ { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "integer", INT_KEYWORD, BINOP_END },
+ { "logical", LOGICAL_KEYWORD, BINOP_END },
+ { "real_16", REAL_S16_KEYWORD, BINOP_END },
+ { "complex", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "sizeof", SIZEOF, BINOP_END },
+ { "real_8", REAL_S8_KEYWORD, BINOP_END },
+ { "real", REAL_KEYWORD, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. Ripped off from ch-exp.y */
+
+static char *tempbuf; /* Current buffer contents */
+static int tempbufsize; /* Size of allocated buffer */
+static int tempbufindex; /* Current index into buffer */
+
+#define GROWBY_MIN_SIZE 64 /* Minimum amount to grow buffer by */
+
+#define CHECKBUF(size) \
+ do { \
+ if (tempbufindex + (size) >= tempbufsize) \
+ { \
+ growbuf_by_size (size); \
+ } \
+ } while (0);
+
+
+/* Grow the static temp buffer if necessary, including allocating the first one
+ on demand. */
+
+static void
+growbuf_by_size (count)
+ int count;
+{
+ int growby;
+
+ growby = max (count, GROWBY_MIN_SIZE);
+ tempbufsize += growby;
+ if (tempbuf == NULL)
+ tempbuf = (char *) malloc (tempbufsize);
+ else
+ tempbuf = (char *) realloc (tempbuf, tempbufsize);
+}
+
+/* Blatantly ripped off from ch-exp.y. This routine recognizes F77
+ string-literals.
+
+ Recognize a string literal. A string literal is a nonzero sequence
+ of characters enclosed in matching single quotes, except that
+ a single character inside single quotes is a character literal, which
+ we reject as a string literal. To embed the terminator character inside
+ a string, it is simply doubled (I.E. 'this''is''one''string') */
+
+static int
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ tokptr++;
+ else
+ break;
+ }
+ tempbuf[tempbufindex++] = *tokptr;
+ }
+ if (*tokptr == '\0' /* no terminator */
+ || tempbufindex == 0) /* no string */
+ return 0;
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return STRING_LITERAL;
+ }
+}
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i,token;
+ char *tokstart;
+ char *tokptr;
+ int tempbufindex;
+ static char *tempbuf;
+ static int tempbufsize;
+
+ retry:
+
+ tokstart = lexptr;
+
+ /* First of all, let us make sure we are not dealing with the
+ special tokens .true. and .false. which evaluate to 1 and 0. */
+
+ if (*lexptr == '.')
+ {
+ for (i=0;boolean_values[i].name != NULL;i++)
+ {
+ if STREQN(tokstart,boolean_values[i].name,
+ strlen(boolean_values[i].name))
+ {
+ lexptr += strlen(boolean_values[i].name);
+ yylval.lval = boolean_values[i].value;
+ return (BOOLEAN_LITERAL);
+ }
+ }
+ }
+
+ /* See if it is a special .foo. operator */
+
+ for (i = 0; dot_ops[i].operator != NULL; i++)
+ if (STREQN(tokstart, dot_ops[i].operator,
+ strlen(dot_ops[i].operator)))
+ {
+ lexptr += strlen(dot_ops[i].operator);
+ yylval.opcode = dot_ops[i].opcode;
+ return dot_ops[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ token = match_string_literal ();
+ if (token != 0)
+ return (token);
+ break;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, got_d = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_e && (*p == 'd' || *p == 'D'))
+ got_dot = got_d = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if ((got_e && (p[-1] == 'e' || p[-1] == 'E')
+ || got_d && (p[-1] == 'd' || p[-1] == 'D'))
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e|got_d,
+ &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen]);
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ return 0;
+
+ lexptr += namelen;
+
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that).
+ Make token type LAST, and put the number (the digits) in yylval. */
+
+ tryname:
+ if (*tokstart == '$')
+ {
+ register int negate = 0;
+
+ c = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (namelen >= 2 && tokstart[1] == '$')
+ {
+ negate = 1;
+ c = 2;
+ }
+ if (c == namelen)
+ {
+ /* Just dollars (one or two) */
+ yylval.lval = - negate;
+ return LAST;
+ }
+ /* Is the rest of the token digits? */
+ for (; c < namelen; c++)
+ if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+ break;
+ if (c == namelen)
+ {
+ yylval.lval = atoi (tokstart + 1 + negate);
+ if (negate)
+ yylval.lval = - yylval.lval;
+ return LAST;
+ }
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+
+ if (*tokstart == '$') {
+ for (c = 0; c < NUM_REGS; c++)
+ if (namelen - 1 == strlen (reg_names[c])
+ && STREQN (tokstart + 1, reg_names[c], namelen - 1))
+ {
+ yylval.lval = c;
+ return REGNAME;
+ }
+ for (c = 0; c < num_std_regs; c++)
+ if (namelen - 1 == strlen (std_regs[c].name)
+ && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
+ {
+ yylval.lval = std_regs[c].regnum;
+ return REGNAME;
+ }
+ }
+ /* Catch specific keywords. */
+
+ for (i = 0; f77_keywords[i].operator != NULL; i++)
+ if (STREQN(tokstart, f77_keywords[i].operator,
+ strlen(f77_keywords[i].operator)))
+ {
+ /* lexptr += strlen(f77_keywords[i].operator); */
+ yylval.opcode = f77_keywords[i].opcode;
+ return f77_keywords[i].token;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ if (*tokstart == '$')
+ {
+ yylval.ivar = lookup_internalvar (copy_name (yylval.sval) + 1);
+ return VARIABLE;
+ }
+
+ /* Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : NULL,
+ NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym
+ && ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
+ || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
new file mode 100644
index 0000000..f9d55b7
--- /dev/null
+++ b/gdb/f-lang.c
@@ -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;
+}
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
new file mode 100644
index 0000000..9611366
--- /dev/null
+++ b/gdb/f-lang.h
@@ -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"
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
new file mode 100644
index 0000000..3540f48
--- /dev/null
+++ b/gdb/f-typeprint.c
@@ -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;
+ }
+}
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
new file mode 100644
index 0000000..0e0cdbc
--- /dev/null
+++ b/gdb/f-valprint.c
@@ -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.");
+}
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index b891237..a87d9a1 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -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
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 62fe1ab..918e1a6 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -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) \
diff --git a/gdb/language.c b/gdb/language.c
index c06decb..f27512c 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -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);
diff --git a/gdb/language.h b/gdb/language.h
index e9a2eff..7ab04db 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -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.
diff --git a/gdb/parse.c b/gdb/parse.c
index 8c387c8..a16be75 100644
--- a/gdb/parse.c
+++ b/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;
diff --git a/gdb/valops.c b/gdb/valops.c
index 24f2c78..06f3527 100644
--- a/gdb/valops.c
+++ b/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 CORE_ADDR
-find_function_addr PARAMS ((value, struct type **));
+static int typecmp PARAMS ((int staticp, struct type *t1[], value_ptr t2[]));
-static CORE_ADDR
-value_push PARAMS ((CORE_ADDR, value));
+static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **));
-static CORE_ADDR
-value_arg_push PARAMS ((CORE_ADDR, value));
+static CORE_ADDR value_push PARAMS ((CORE_ADDR, value_ptr));
-static value
-search_struct_field PARAMS ((char *, value, int, struct type *, int));
+static CORE_ADDR value_arg_push PARAMS ((CORE_ADDR, value_ptr));
-static value
-search_struct_method PARAMS ((char *, value *, value *, int, int *,
- struct type *));
+static value_ptr search_struct_field PARAMS ((char *, value_ptr, int,
+ struct type *, int));
-static int
-check_field_in PARAMS ((struct type *, const char *));
+static value_ptr search_struct_method PARAMS ((char *, value_ptr *,
+ value_ptr *,
+ int, int *, struct type *));
-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;
+}
diff --git a/gdb/value.h b/gdb/value.h
index 6982258..3c4a047 100644
--- a/gdb/value.h
+++ b/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) */