119370Spst/* YACC parser for Fortran expressions, for GDB.
298944Sobrien   Copyright 1986, 1989, 1990, 1991, 1993, 1994, 1995, 1996, 2000, 2001
398944Sobrien   Free Software Foundation, Inc.
498944Sobrien
519370Spst   Contributed by Motorola.  Adapted from the C parser by Farooq Butt
619370Spst   (fmbutt@engage.sps.mot.com).
719370Spst
819370SpstThis file is part of GDB.
919370Spst
1019370SpstThis program is free software; you can redistribute it and/or modify
1119370Spstit under the terms of the GNU General Public License as published by
1219370Spstthe Free Software Foundation; either version 2 of the License, or
1319370Spst(at your option) any later version.
1419370Spst
1519370SpstThis program is distributed in the hope that it will be useful,
1619370Spstbut WITHOUT ANY WARRANTY; without even the implied warranty of
1719370SpstMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1819370SpstGNU General Public License for more details.
1919370Spst
2019370SpstYou should have received a copy of the GNU General Public License
2119370Spstalong with this program; if not, write to the Free Software
2219370SpstFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2319370Spst
2419370Spst/* This was blantantly ripped off the C expression parser, please
2519370Spst   be aware of that as you look at its basic structure -FMB */
2619370Spst
2719370Spst/* Parse a F77 expression from text in a string,
2819370Spst   and return the result as a  struct expression  pointer.
2919370Spst   That structure contains arithmetic operations in reverse polish,
3019370Spst   with constants represented by operations that are followed by special data.
3119370Spst   See expression.h for the details of the format.
3219370Spst   What is important here is that it can be built up sequentially
3319370Spst   during the process of parsing; the lower levels of the tree always
3419370Spst   come first in the result.
3519370Spst
3619370Spst   Note that malloc's and realloc's in this file are transformed to
3719370Spst   xmalloc and xrealloc respectively by the same sed command in the
3819370Spst   makefile that remaps any other malloc/realloc inserted by the parser
3919370Spst   generator.  Doing this with #defines and trying to control the interaction
4019370Spst   with include files (<malloc.h> and <stdlib.h> for example) just became
4119370Spst   too messy, particularly when such includes can be inserted at random
4219370Spst   times by the parser generator.  */
4319370Spst
4419370Spst%{
4519370Spst
4619370Spst#include "defs.h"
4719370Spst#include "gdb_string.h"
4819370Spst#include "expression.h"
4919370Spst#include "value.h"
5019370Spst#include "parser-defs.h"
5119370Spst#include "language.h"
5219370Spst#include "f-lang.h"
5319370Spst#include "bfd.h" /* Required by objfiles.h.  */
5419370Spst#include "symfile.h" /* Required by objfiles.h.  */
5519370Spst#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
56130803Smarcel#include "block.h"
5798944Sobrien#include <ctype.h>
5819370Spst
5919370Spst/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
6019370Spst   as well as gratuitiously global symbol names, so we can have multiple
6119370Spst   yacc generated parsers in gdb.  Note that these are only the variables
6219370Spst   produced by yacc.  If other parser generators (bison, byacc, etc) produce
6319370Spst   additional global names that conflict at link time, then those parser
6419370Spst   generators need to be fixed instead of adding those names to this list. */
6519370Spst
6619370Spst#define	yymaxdepth f_maxdepth
6719370Spst#define	yyparse	f_parse
6819370Spst#define	yylex	f_lex
6919370Spst#define	yyerror	f_error
7019370Spst#define	yylval	f_lval
7119370Spst#define	yychar	f_char
7219370Spst#define	yydebug	f_debug
7319370Spst#define	yypact	f_pact
7419370Spst#define	yyr1	f_r1
7519370Spst#define	yyr2	f_r2
7619370Spst#define	yydef	f_def
7719370Spst#define	yychk	f_chk
7819370Spst#define	yypgo	f_pgo
7919370Spst#define	yyact	f_act
8019370Spst#define	yyexca	f_exca
8119370Spst#define yyerrflag f_errflag
8219370Spst#define yynerrs	f_nerrs
8319370Spst#define	yyps	f_ps
8419370Spst#define	yypv	f_pv
8519370Spst#define	yys	f_s
8619370Spst#define	yy_yys	f_yys
8719370Spst#define	yystate	f_state
8819370Spst#define	yytmp	f_tmp
8919370Spst#define	yyv	f_v
9019370Spst#define	yy_yyv	f_yyv
9119370Spst#define	yyval	f_val
9219370Spst#define	yylloc	f_lloc
9319370Spst#define yyreds	f_reds		/* With YYDEBUG defined */
9419370Spst#define yytoks	f_toks		/* With YYDEBUG defined */
95130803Smarcel#define yyname	f_name		/* With YYDEBUG defined */
96130803Smarcel#define yyrule	f_rule		/* With YYDEBUG defined */
9719370Spst#define yylhs	f_yylhs
9819370Spst#define yylen	f_yylen
9919370Spst#define yydefred f_yydefred
10019370Spst#define yydgoto	f_yydgoto
10119370Spst#define yysindex f_yysindex
10219370Spst#define yyrindex f_yyrindex
10319370Spst#define yygindex f_yygindex
10419370Spst#define yytable	 f_yytable
10519370Spst#define yycheck	 f_yycheck
10619370Spst
10719370Spst#ifndef YYDEBUG
108130803Smarcel#define	YYDEBUG	1		/* Default to yydebug support */
10919370Spst#endif
11019370Spst
111130803Smarcel#define YYFPRINTF parser_fprintf
112130803Smarcel
11398944Sobrienint yyparse (void);
11419370Spst
11598944Sobrienstatic int yylex (void);
11619370Spst
11798944Sobrienvoid yyerror (char *);
11819370Spst
11998944Sobrienstatic void growbuf_by_size (int);
12046283Sdfr
12198944Sobrienstatic int match_string_literal (void);
12246283Sdfr
12319370Spst%}
12419370Spst
12519370Spst/* Although the yacc "value" of an expression is not used,
12619370Spst   since the result is stored in the structure being created,
12719370Spst   other node types do have values.  */
12819370Spst
12919370Spst%union
13019370Spst  {
13119370Spst    LONGEST lval;
13219370Spst    struct {
13319370Spst      LONGEST val;
13419370Spst      struct type *type;
13519370Spst    } typed_val;
13619370Spst    DOUBLEST dval;
13719370Spst    struct symbol *sym;
13819370Spst    struct type *tval;
13919370Spst    struct stoken sval;
14019370Spst    struct ttype tsym;
14119370Spst    struct symtoken ssym;
14219370Spst    int voidval;
14319370Spst    struct block *bval;
14419370Spst    enum exp_opcode opcode;
14519370Spst    struct internalvar *ivar;
14619370Spst
14719370Spst    struct type **tvec;
14819370Spst    int *ivec;
14919370Spst  }
15019370Spst
15119370Spst%{
15219370Spst/* YYSTYPE gets defined by %union */
15398944Sobrienstatic int parse_number (char *, int, int, YYSTYPE *);
15419370Spst%}
15519370Spst
15619370Spst%type <voidval> exp  type_exp start variable
15719370Spst%type <tval> type typebase
15819370Spst%type <tvec> nonempty_typelist
15919370Spst/* %type <bval> block */
16019370Spst
16119370Spst/* Fancy type parsing.  */
16219370Spst%type <voidval> func_mod direct_abs_decl abs_decl
16319370Spst%type <tval> ptype
16419370Spst
16519370Spst%token <typed_val> INT
16619370Spst%token <dval> FLOAT
16719370Spst
16819370Spst/* Both NAME and TYPENAME tokens represent symbols in the input,
16919370Spst   and both convey their data as strings.
17019370Spst   But a TYPENAME is a string that happens to be defined as a typedef
17119370Spst   or builtin type name (such as int or char)
17219370Spst   and a NAME is any other symbol.
17319370Spst   Contexts where this distinction is not important can use the
17419370Spst   nonterminal "name", which matches either NAME or TYPENAME.  */
17519370Spst
17619370Spst%token <sval> STRING_LITERAL
17719370Spst%token <lval> BOOLEAN_LITERAL
17819370Spst%token <ssym> NAME
17919370Spst%token <tsym> TYPENAME
18019370Spst%type <sval> name
18119370Spst%type <ssym> name_not_typename
18219370Spst%type <tsym> typename
18319370Spst
18419370Spst/* A NAME_OR_INT is a symbol which is not known in the symbol table,
18519370Spst   but which would parse as a valid number in the current input radix.
18619370Spst   E.g. "c" when input_radix==16.  Depending on the parse, it will be
18719370Spst   turned into a name or into a number.  */
18819370Spst
18919370Spst%token <ssym> NAME_OR_INT
19019370Spst
19119370Spst%token  SIZEOF
19219370Spst%token ERROR
19319370Spst
19419370Spst/* Special type cases, put in to allow the parser to distinguish different
19519370Spst   legal basetypes.  */
19619370Spst%token INT_KEYWORD INT_S2_KEYWORD LOGICAL_S1_KEYWORD LOGICAL_S2_KEYWORD
19719370Spst%token LOGICAL_KEYWORD REAL_KEYWORD REAL_S8_KEYWORD REAL_S16_KEYWORD
19819370Spst%token COMPLEX_S8_KEYWORD COMPLEX_S16_KEYWORD COMPLEX_S32_KEYWORD
19919370Spst%token BOOL_AND BOOL_OR BOOL_NOT
20019370Spst%token <lval> CHARACTER
20119370Spst
20219370Spst%token <voidval> VARIABLE
20319370Spst
20419370Spst%token <opcode> ASSIGN_MODIFY
20519370Spst
20619370Spst%left ','
20719370Spst%left ABOVE_COMMA
20819370Spst%right '=' ASSIGN_MODIFY
20919370Spst%right '?'
21019370Spst%left BOOL_OR
21119370Spst%right BOOL_NOT
21219370Spst%left BOOL_AND
21319370Spst%left '|'
21419370Spst%left '^'
21519370Spst%left '&'
21619370Spst%left EQUAL NOTEQUAL
21719370Spst%left LESSTHAN GREATERTHAN LEQ GEQ
21819370Spst%left LSH RSH
21919370Spst%left '@'
22019370Spst%left '+' '-'
22119370Spst%left '*' '/' '%'
22219370Spst%right UNARY
22319370Spst%right '('
22419370Spst
22519370Spst
22619370Spst%%
22719370Spst
22819370Spststart   :	exp
22919370Spst	|	type_exp
23019370Spst	;
23119370Spst
23219370Spsttype_exp:	type
23319370Spst			{ write_exp_elt_opcode(OP_TYPE);
23419370Spst			  write_exp_elt_type($1);
23519370Spst			  write_exp_elt_opcode(OP_TYPE); }
23619370Spst	;
23719370Spst
23819370Spstexp     :       '(' exp ')'
23919370Spst        		{ }
24019370Spst        ;
24119370Spst
24219370Spst/* Expressions, not including the comma operator.  */
24319370Spstexp	:	'*' exp    %prec UNARY
24419370Spst			{ write_exp_elt_opcode (UNOP_IND); }
245130803Smarcel	;
24619370Spst
24719370Spstexp	:	'&' exp    %prec UNARY
24819370Spst			{ write_exp_elt_opcode (UNOP_ADDR); }
249130803Smarcel	;
25019370Spst
25119370Spstexp	:	'-' exp    %prec UNARY
25219370Spst			{ write_exp_elt_opcode (UNOP_NEG); }
25319370Spst	;
25419370Spst
25519370Spstexp	:	BOOL_NOT exp    %prec UNARY
25619370Spst			{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
25719370Spst	;
25819370Spst
25919370Spstexp	:	'~' exp    %prec UNARY
26019370Spst			{ write_exp_elt_opcode (UNOP_COMPLEMENT); }
26119370Spst	;
26219370Spst
26319370Spstexp	:	SIZEOF exp       %prec UNARY
26419370Spst			{ write_exp_elt_opcode (UNOP_SIZEOF); }
26519370Spst	;
26619370Spst
26719370Spst/* No more explicit array operators, we treat everything in F77 as
26819370Spst   a function call.  The disambiguation as to whether we are
26919370Spst   doing a subscript operation or a function call is done
27019370Spst   later in eval.c.  */
27119370Spst
27219370Spstexp	:	exp '('
27319370Spst			{ start_arglist (); }
27419370Spst		arglist ')'
27519370Spst			{ write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST);
27619370Spst			  write_exp_elt_longcst ((LONGEST) end_arglist ());
27719370Spst			  write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST); }
27819370Spst	;
27919370Spst
28019370Spstarglist	:
28119370Spst	;
28219370Spst
28319370Spstarglist	:	exp
28419370Spst			{ arglist_len = 1; }
28519370Spst	;
28619370Spst
28719370Spstarglist :      substring
28819370Spst                        { arglist_len = 2;}
289130803Smarcel	;
29019370Spst
29119370Spstarglist	:	arglist ',' exp   %prec ABOVE_COMMA
29219370Spst			{ arglist_len++; }
29319370Spst	;
29419370Spst
29519370Spstsubstring:	exp ':' exp   %prec ABOVE_COMMA
29619370Spst			{ }
29719370Spst	;
29819370Spst
29919370Spst
30019370Spstcomplexnum:     exp ',' exp
30119370Spst                	{ }
30219370Spst        ;
30319370Spst
30419370Spstexp	:	'(' complexnum ')'
30519370Spst                	{ write_exp_elt_opcode(OP_COMPLEX); }
30619370Spst	;
30719370Spst
30819370Spstexp	:	'(' type ')' exp  %prec UNARY
30919370Spst			{ write_exp_elt_opcode (UNOP_CAST);
31019370Spst			  write_exp_elt_type ($2);
31119370Spst			  write_exp_elt_opcode (UNOP_CAST); }
31219370Spst	;
31319370Spst
31419370Spst/* Binary operators in order of decreasing precedence.  */
31519370Spst
31619370Spstexp	:	exp '@' exp
31719370Spst			{ write_exp_elt_opcode (BINOP_REPEAT); }
31819370Spst	;
31919370Spst
32019370Spstexp	:	exp '*' exp
32119370Spst			{ write_exp_elt_opcode (BINOP_MUL); }
32219370Spst	;
32319370Spst
32419370Spstexp	:	exp '/' exp
32519370Spst			{ write_exp_elt_opcode (BINOP_DIV); }
32619370Spst	;
32719370Spst
32819370Spstexp	:	exp '%' exp
32919370Spst			{ write_exp_elt_opcode (BINOP_REM); }
33019370Spst	;
33119370Spst
33219370Spstexp	:	exp '+' exp
33319370Spst			{ write_exp_elt_opcode (BINOP_ADD); }
33419370Spst	;
33519370Spst
33619370Spstexp	:	exp '-' exp
33719370Spst			{ write_exp_elt_opcode (BINOP_SUB); }
33819370Spst	;
33919370Spst
34019370Spstexp	:	exp LSH exp
34119370Spst			{ write_exp_elt_opcode (BINOP_LSH); }
34219370Spst	;
34319370Spst
34419370Spstexp	:	exp RSH exp
34519370Spst			{ write_exp_elt_opcode (BINOP_RSH); }
34619370Spst	;
34719370Spst
34819370Spstexp	:	exp EQUAL exp
34919370Spst			{ write_exp_elt_opcode (BINOP_EQUAL); }
35019370Spst	;
35119370Spst
35219370Spstexp	:	exp NOTEQUAL exp
35319370Spst			{ write_exp_elt_opcode (BINOP_NOTEQUAL); }
35419370Spst	;
35519370Spst
35619370Spstexp	:	exp LEQ exp
35719370Spst			{ write_exp_elt_opcode (BINOP_LEQ); }
35819370Spst	;
35919370Spst
36019370Spstexp	:	exp GEQ exp
36119370Spst			{ write_exp_elt_opcode (BINOP_GEQ); }
36219370Spst	;
36319370Spst
36419370Spstexp	:	exp LESSTHAN exp
36519370Spst			{ write_exp_elt_opcode (BINOP_LESS); }
36619370Spst	;
36719370Spst
36819370Spstexp	:	exp GREATERTHAN exp
36919370Spst			{ write_exp_elt_opcode (BINOP_GTR); }
37019370Spst	;
37119370Spst
37219370Spstexp	:	exp '&' exp
37319370Spst			{ write_exp_elt_opcode (BINOP_BITWISE_AND); }
37419370Spst	;
37519370Spst
37619370Spstexp	:	exp '^' exp
37719370Spst			{ write_exp_elt_opcode (BINOP_BITWISE_XOR); }
37819370Spst	;
37919370Spst
38019370Spstexp	:	exp '|' exp
38119370Spst			{ write_exp_elt_opcode (BINOP_BITWISE_IOR); }
38219370Spst	;
38319370Spst
38419370Spstexp     :       exp BOOL_AND exp
38519370Spst			{ write_exp_elt_opcode (BINOP_LOGICAL_AND); }
38619370Spst	;
38719370Spst
38819370Spst
38919370Spstexp	:	exp BOOL_OR exp
39019370Spst			{ write_exp_elt_opcode (BINOP_LOGICAL_OR); }
39119370Spst	;
39219370Spst
39319370Spstexp	:	exp '=' exp
39419370Spst			{ write_exp_elt_opcode (BINOP_ASSIGN); }
39519370Spst	;
39619370Spst
39719370Spstexp	:	exp ASSIGN_MODIFY exp
39819370Spst			{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
39919370Spst			  write_exp_elt_opcode ($2);
40019370Spst			  write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
40119370Spst	;
40219370Spst
40319370Spstexp	:	INT
40419370Spst			{ write_exp_elt_opcode (OP_LONG);
40519370Spst			  write_exp_elt_type ($1.type);
40619370Spst			  write_exp_elt_longcst ((LONGEST)($1.val));
40719370Spst			  write_exp_elt_opcode (OP_LONG); }
40819370Spst	;
40919370Spst
41019370Spstexp	:	NAME_OR_INT
41119370Spst			{ YYSTYPE val;
41219370Spst			  parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
41319370Spst			  write_exp_elt_opcode (OP_LONG);
41419370Spst			  write_exp_elt_type (val.typed_val.type);
41519370Spst			  write_exp_elt_longcst ((LONGEST)val.typed_val.val);
41619370Spst			  write_exp_elt_opcode (OP_LONG); }
41719370Spst	;
41819370Spst
41919370Spstexp	:	FLOAT
42019370Spst			{ write_exp_elt_opcode (OP_DOUBLE);
42119370Spst			  write_exp_elt_type (builtin_type_f_real_s8);
42219370Spst			  write_exp_elt_dblcst ($1);
42319370Spst			  write_exp_elt_opcode (OP_DOUBLE); }
42419370Spst	;
42519370Spst
42619370Spstexp	:	variable
42719370Spst	;
42819370Spst
42919370Spstexp	:	VARIABLE
43019370Spst	;
43119370Spst
43219370Spstexp	:	SIZEOF '(' type ')'	%prec UNARY
43319370Spst			{ write_exp_elt_opcode (OP_LONG);
43419370Spst			  write_exp_elt_type (builtin_type_f_integer);
43519370Spst			  CHECK_TYPEDEF ($3);
43619370Spst			  write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
43719370Spst			  write_exp_elt_opcode (OP_LONG); }
43819370Spst	;
43919370Spst
44019370Spstexp     :       BOOLEAN_LITERAL
44119370Spst			{ write_exp_elt_opcode (OP_BOOL);
44219370Spst			  write_exp_elt_longcst ((LONGEST) $1);
44319370Spst			  write_exp_elt_opcode (OP_BOOL);
44419370Spst			}
44519370Spst        ;
44619370Spst
44719370Spstexp	:	STRING_LITERAL
44819370Spst			{
44919370Spst			  write_exp_elt_opcode (OP_STRING);
45019370Spst			  write_exp_string ($1);
45119370Spst			  write_exp_elt_opcode (OP_STRING);
45219370Spst			}
45319370Spst	;
45419370Spst
45519370Spstvariable:	name_not_typename
45619370Spst			{ struct symbol *sym = $1.sym;
45719370Spst
45819370Spst			  if (sym)
45919370Spst			    {
46019370Spst			      if (symbol_read_needs_frame (sym))
46119370Spst				{
46219370Spst				  if (innermost_block == 0 ||
46319370Spst				      contained_in (block_found,
46419370Spst						    innermost_block))
46519370Spst				    innermost_block = block_found;
46619370Spst				}
46719370Spst			      write_exp_elt_opcode (OP_VAR_VALUE);
46819370Spst			      /* We want to use the selected frame, not
46919370Spst				 another more inner frame which happens to
47019370Spst				 be in the same block.  */
47119370Spst			      write_exp_elt_block (NULL);
47219370Spst			      write_exp_elt_sym (sym);
47319370Spst			      write_exp_elt_opcode (OP_VAR_VALUE);
47419370Spst			      break;
47519370Spst			    }
47619370Spst			  else
47719370Spst			    {
47819370Spst			      struct minimal_symbol *msymbol;
479130803Smarcel			      char *arg = copy_name ($1.stoken);
48019370Spst
48119370Spst			      msymbol =
48219370Spst				lookup_minimal_symbol (arg, NULL, NULL);
48319370Spst			      if (msymbol != NULL)
48419370Spst				{
48519370Spst				  write_exp_msymbol (msymbol,
48619370Spst						     lookup_function_type (builtin_type_int),
48719370Spst						     builtin_type_int);
48819370Spst				}
48919370Spst			      else if (!have_full_symbols () && !have_partial_symbols ())
49019370Spst				error ("No symbol table is loaded.  Use the \"file\" command.");
49119370Spst			      else
49219370Spst				error ("No symbol \"%s\" in current context.",
49319370Spst				       copy_name ($1.stoken));
49419370Spst			    }
49519370Spst			}
49619370Spst	;
49719370Spst
49819370Spst
49919370Spsttype    :       ptype
50019370Spst        ;
50119370Spst
50219370Spstptype	:	typebase
50319370Spst	|	typebase abs_decl
50419370Spst		{
50519370Spst		  /* This is where the interesting stuff happens.  */
50619370Spst		  int done = 0;
50719370Spst		  int array_size;
50819370Spst		  struct type *follow_type = $1;
50919370Spst		  struct type *range_type;
51019370Spst
51119370Spst		  while (!done)
51219370Spst		    switch (pop_type ())
51319370Spst		      {
51419370Spst		      case tp_end:
51519370Spst			done = 1;
51619370Spst			break;
51719370Spst		      case tp_pointer:
51819370Spst			follow_type = lookup_pointer_type (follow_type);
51919370Spst			break;
52019370Spst		      case tp_reference:
52119370Spst			follow_type = lookup_reference_type (follow_type);
52219370Spst			break;
52319370Spst		      case tp_array:
52419370Spst			array_size = pop_type_int ();
52519370Spst			if (array_size != -1)
52619370Spst			  {
52719370Spst			    range_type =
52819370Spst			      create_range_type ((struct type *) NULL,
52919370Spst						 builtin_type_f_integer, 0,
53019370Spst						 array_size - 1);
53119370Spst			    follow_type =
53219370Spst			      create_array_type ((struct type *) NULL,
53319370Spst						 follow_type, range_type);
53419370Spst			  }
53519370Spst			else
53619370Spst			  follow_type = lookup_pointer_type (follow_type);
53719370Spst			break;
53819370Spst		      case tp_function:
53919370Spst			follow_type = lookup_function_type (follow_type);
54019370Spst			break;
54119370Spst		      }
54219370Spst		  $$ = follow_type;
54319370Spst		}
54419370Spst	;
54519370Spst
54619370Spstabs_decl:	'*'
54719370Spst			{ push_type (tp_pointer); $$ = 0; }
54819370Spst	|	'*' abs_decl
54919370Spst			{ push_type (tp_pointer); $$ = $2; }
55019370Spst	|	'&'
55119370Spst			{ push_type (tp_reference); $$ = 0; }
55219370Spst	|	'&' abs_decl
55319370Spst			{ push_type (tp_reference); $$ = $2; }
55419370Spst	|	direct_abs_decl
55519370Spst	;
55619370Spst
55719370Spstdirect_abs_decl: '(' abs_decl ')'
55819370Spst			{ $$ = $2; }
55919370Spst	| 	direct_abs_decl func_mod
56019370Spst			{ push_type (tp_function); }
56119370Spst	|	func_mod
56219370Spst			{ push_type (tp_function); }
56319370Spst	;
56419370Spst
56519370Spstfunc_mod:	'(' ')'
56619370Spst			{ $$ = 0; }
56719370Spst	|	'(' nonempty_typelist ')'
568130803Smarcel			{ free ($2); $$ = 0; }
56919370Spst	;
57019370Spst
57119370Spsttypebase  /* Implements (approximately): (type-qualifier)* type-specifier */
57219370Spst	:	TYPENAME
57319370Spst			{ $$ = $1.type; }
57419370Spst	|	INT_KEYWORD
57519370Spst			{ $$ = builtin_type_f_integer; }
57619370Spst	|	INT_S2_KEYWORD
57719370Spst			{ $$ = builtin_type_f_integer_s2; }
57819370Spst	|	CHARACTER
57919370Spst			{ $$ = builtin_type_f_character; }
58019370Spst	|	LOGICAL_KEYWORD
58119370Spst			{ $$ = builtin_type_f_logical;}
58219370Spst	|	LOGICAL_S2_KEYWORD
58319370Spst			{ $$ = builtin_type_f_logical_s2;}
58419370Spst	|	LOGICAL_S1_KEYWORD
58519370Spst			{ $$ = builtin_type_f_logical_s1;}
58619370Spst	|	REAL_KEYWORD
58719370Spst			{ $$ = builtin_type_f_real;}
58819370Spst	|       REAL_S8_KEYWORD
58919370Spst			{ $$ = builtin_type_f_real_s8;}
59019370Spst	|	REAL_S16_KEYWORD
59119370Spst			{ $$ = builtin_type_f_real_s16;}
59219370Spst	|	COMPLEX_S8_KEYWORD
59319370Spst			{ $$ = builtin_type_f_complex_s8;}
59419370Spst	|	COMPLEX_S16_KEYWORD
59519370Spst			{ $$ = builtin_type_f_complex_s16;}
59619370Spst	|	COMPLEX_S32_KEYWORD
59719370Spst			{ $$ = builtin_type_f_complex_s32;}
59819370Spst	;
59919370Spst
60019370Spsttypename:	TYPENAME
60119370Spst	;
60219370Spst
60319370Spstnonempty_typelist
60419370Spst	:	type
60519370Spst		{ $$ = (struct type **) malloc (sizeof (struct type *) * 2);
60619370Spst		  $<ivec>$[0] = 1;	/* Number of types in vector */
60719370Spst		  $$[1] = $1;
60819370Spst		}
60919370Spst	|	nonempty_typelist ',' type
61019370Spst		{ int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
61119370Spst		  $$ = (struct type **) realloc ((char *) $1, len);
61219370Spst		  $$[$<ivec>$[0]] = $3;
61319370Spst		}
61419370Spst	;
61519370Spst
61619370Spstname	:	NAME
61719370Spst			{ $$ = $1.stoken; }
61819370Spst	|	TYPENAME
61919370Spst			{ $$ = $1.stoken; }
62019370Spst	|	NAME_OR_INT
62119370Spst			{ $$ = $1.stoken; }
62219370Spst	;
62319370Spst
62419370Spstname_not_typename :	NAME
62519370Spst/* These would be useful if name_not_typename was useful, but it is just
62619370Spst   a fake for "variable", so these cause reduce/reduce conflicts because
62719370Spst   the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
62819370Spst   =exp) or just an exp.  If name_not_typename was ever used in an lvalue
62919370Spst   context where only a name could occur, this might be useful.
63019370Spst  	|	NAME_OR_INT
63119370Spst   */
63219370Spst	;
63319370Spst
63419370Spst%%
63519370Spst
63619370Spst/* Take care of parsing a number (anything that starts with a digit).
63719370Spst   Set yylval and return the token type; update lexptr.
63819370Spst   LEN is the number of characters in it.  */
63919370Spst
64019370Spst/*** Needs some error checking for the float case ***/
64119370Spst
64219370Spststatic int
64319370Spstparse_number (p, len, parsed_float, putithere)
644130803Smarcel     char *p;
645130803Smarcel     int len;
64619370Spst     int parsed_float;
64719370Spst     YYSTYPE *putithere;
64819370Spst{
649130803Smarcel  LONGEST n = 0;
650130803Smarcel  LONGEST prevn = 0;
651130803Smarcel  int c;
652130803Smarcel  int base = input_radix;
65319370Spst  int unsigned_p = 0;
65419370Spst  int long_p = 0;
65546283Sdfr  ULONGEST high_bit;
65619370Spst  struct type *signed_type;
65719370Spst  struct type *unsigned_type;
65819370Spst
65919370Spst  if (parsed_float)
66019370Spst    {
66119370Spst      /* It's a float since it contains a point or an exponent.  */
66219370Spst      /* [dD] is not understood as an exponent by atof, change it to 'e'.  */
66319370Spst      char *tmp, *tmp2;
66419370Spst
66598944Sobrien      tmp = xstrdup (p);
66619370Spst      for (tmp2 = tmp; *tmp2; ++tmp2)
66719370Spst	if (*tmp2 == 'd' || *tmp2 == 'D')
66819370Spst	  *tmp2 = 'e';
66919370Spst      putithere->dval = atof (tmp);
67019370Spst      free (tmp);
67119370Spst      return FLOAT;
67219370Spst    }
67319370Spst
67419370Spst  /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
67519370Spst  if (p[0] == '0')
67619370Spst    switch (p[1])
67719370Spst      {
67819370Spst      case 'x':
67919370Spst      case 'X':
68019370Spst	if (len >= 3)
68119370Spst	  {
68219370Spst	    p += 2;
68319370Spst	    base = 16;
68419370Spst	    len -= 2;
68519370Spst	  }
68619370Spst	break;
68719370Spst
68819370Spst      case 't':
68919370Spst      case 'T':
69019370Spst      case 'd':
69119370Spst      case 'D':
69219370Spst	if (len >= 3)
69319370Spst	  {
69419370Spst	    p += 2;
69519370Spst	    base = 10;
69619370Spst	    len -= 2;
69719370Spst	  }
69819370Spst	break;
69919370Spst
70019370Spst      default:
70119370Spst	base = 8;
70219370Spst	break;
70319370Spst      }
70419370Spst
70519370Spst  while (len-- > 0)
70619370Spst    {
70719370Spst      c = *p++;
70898944Sobrien      if (isupper (c))
70998944Sobrien	c = tolower (c);
71098944Sobrien      if (len == 0 && c == 'l')
71198944Sobrien	long_p = 1;
71298944Sobrien      else if (len == 0 && c == 'u')
71398944Sobrien	unsigned_p = 1;
71419370Spst      else
71519370Spst	{
71698944Sobrien	  int i;
71798944Sobrien	  if (c >= '0' && c <= '9')
71898944Sobrien	    i = c - '0';
71998944Sobrien	  else if (c >= 'a' && c <= 'f')
72098944Sobrien	    i = c - 'a' + 10;
72119370Spst	  else
72219370Spst	    return ERROR;	/* Char not a digit */
72398944Sobrien	  if (i >= base)
72498944Sobrien	    return ERROR;		/* Invalid digit in this base */
72598944Sobrien	  n *= base;
72698944Sobrien	  n += i;
72719370Spst	}
72819370Spst      /* Portably test for overflow (only works for nonzero values, so make
72919370Spst	 a second check for zero).  */
73019370Spst      if ((prevn >= n) && n != 0)
73119370Spst	unsigned_p=1;		/* Try something unsigned */
73219370Spst      /* If range checking enabled, portably test for unsigned overflow.  */
73319370Spst      if (RANGE_CHECK && n != 0)
73419370Spst	{
73519370Spst	  if ((unsigned_p && (unsigned)prevn >= (unsigned)n))
73619370Spst	    range_error("Overflow on numeric constant.");
73719370Spst	}
73819370Spst      prevn = n;
73919370Spst    }
74019370Spst
74119370Spst  /* If the number is too big to be an int, or it's got an l suffix
74219370Spst     then it's a long.  Work out if this has to be a long by
74319370Spst     shifting right and and seeing if anything remains, and the
74419370Spst     target int size is different to the target long size.
74519370Spst
74619370Spst     In the expression below, we could have tested
74719370Spst     (n >> TARGET_INT_BIT)
74819370Spst     to see if it was zero,
74919370Spst     but too many compilers warn about that, when ints and longs
75019370Spst     are the same size.  So we shift it twice, with fewer bits
75119370Spst     each time, for the same result.  */
75219370Spst
75319370Spst  if ((TARGET_INT_BIT != TARGET_LONG_BIT
75419370Spst       && ((n >> 2) >> (TARGET_INT_BIT-2)))   /* Avoid shift warning */
75519370Spst      || long_p)
75619370Spst    {
75746283Sdfr      high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
75819370Spst      unsigned_type = builtin_type_unsigned_long;
75919370Spst      signed_type = builtin_type_long;
76019370Spst    }
76119370Spst  else
76219370Spst    {
76346283Sdfr      high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
76419370Spst      unsigned_type = builtin_type_unsigned_int;
76519370Spst      signed_type = builtin_type_int;
76619370Spst    }
76719370Spst
76819370Spst  putithere->typed_val.val = n;
76919370Spst
77019370Spst  /* If the high bit of the worked out type is set then this number
77119370Spst     has to be unsigned. */
77219370Spst
77319370Spst  if (unsigned_p || (n & high_bit))
77419370Spst    putithere->typed_val.type = unsigned_type;
77519370Spst  else
77619370Spst    putithere->typed_val.type = signed_type;
77719370Spst
77819370Spst  return INT;
77919370Spst}
78019370Spst
78119370Spststruct token
78219370Spst{
78319370Spst  char *operator;
78419370Spst  int token;
78519370Spst  enum exp_opcode opcode;
78619370Spst};
78719370Spst
78819370Spststatic const struct token dot_ops[] =
78919370Spst{
79019370Spst  { ".and.", BOOL_AND, BINOP_END },
79119370Spst  { ".AND.", BOOL_AND, BINOP_END },
79219370Spst  { ".or.", BOOL_OR, BINOP_END },
79319370Spst  { ".OR.", BOOL_OR, BINOP_END },
79419370Spst  { ".not.", BOOL_NOT, BINOP_END },
79519370Spst  { ".NOT.", BOOL_NOT, BINOP_END },
79619370Spst  { ".eq.", EQUAL, BINOP_END },
79719370Spst  { ".EQ.", EQUAL, BINOP_END },
79819370Spst  { ".eqv.", EQUAL, BINOP_END },
79919370Spst  { ".NEQV.", NOTEQUAL, BINOP_END },
80019370Spst  { ".neqv.", NOTEQUAL, BINOP_END },
80119370Spst  { ".EQV.", EQUAL, BINOP_END },
80219370Spst  { ".ne.", NOTEQUAL, BINOP_END },
80319370Spst  { ".NE.", NOTEQUAL, BINOP_END },
80419370Spst  { ".le.", LEQ, BINOP_END },
80519370Spst  { ".LE.", LEQ, BINOP_END },
80619370Spst  { ".ge.", GEQ, BINOP_END },
80719370Spst  { ".GE.", GEQ, BINOP_END },
80819370Spst  { ".gt.", GREATERTHAN, BINOP_END },
80919370Spst  { ".GT.", GREATERTHAN, BINOP_END },
81019370Spst  { ".lt.", LESSTHAN, BINOP_END },
81119370Spst  { ".LT.", LESSTHAN, BINOP_END },
81219370Spst  { NULL, 0, 0 }
81319370Spst};
81419370Spst
81519370Spststruct f77_boolean_val
81619370Spst{
81719370Spst  char *name;
81819370Spst  int value;
81919370Spst};
82019370Spst
82119370Spststatic const struct f77_boolean_val boolean_values[]  =
82219370Spst{
82319370Spst  { ".true.", 1 },
82419370Spst  { ".TRUE.", 1 },
82519370Spst  { ".false.", 0 },
82619370Spst  { ".FALSE.", 0 },
82719370Spst  { NULL, 0 }
82819370Spst};
82919370Spst
83019370Spststatic const struct token f77_keywords[] =
83119370Spst{
83219370Spst  { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END },
83319370Spst  { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END },
83419370Spst  { "character", CHARACTER, BINOP_END },
83519370Spst  { "integer_2", INT_S2_KEYWORD, BINOP_END },
83619370Spst  { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END },
83719370Spst  { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END },
83819370Spst  { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END },
83919370Spst  { "integer", INT_KEYWORD, BINOP_END },
84019370Spst  { "logical", LOGICAL_KEYWORD, BINOP_END },
84119370Spst  { "real_16", REAL_S16_KEYWORD, BINOP_END },
84219370Spst  { "complex", COMPLEX_S8_KEYWORD, BINOP_END },
84319370Spst  { "sizeof", SIZEOF, BINOP_END },
84419370Spst  { "real_8", REAL_S8_KEYWORD, BINOP_END },
84519370Spst  { "real", REAL_KEYWORD, BINOP_END },
84619370Spst  { NULL, 0, 0 }
84719370Spst};
84819370Spst
84919370Spst/* Implementation of a dynamically expandable buffer for processing input
85019370Spst   characters acquired through lexptr and building a value to return in
85119370Spst   yylval. Ripped off from ch-exp.y */
85219370Spst
85319370Spststatic char *tempbuf;		/* Current buffer contents */
85419370Spststatic int tempbufsize;		/* Size of allocated buffer */
85519370Spststatic int tempbufindex;	/* Current index into buffer */
85619370Spst
85719370Spst#define GROWBY_MIN_SIZE 64	/* Minimum amount to grow buffer by */
85819370Spst
85919370Spst#define CHECKBUF(size) \
86019370Spst  do { \
86119370Spst    if (tempbufindex + (size) >= tempbufsize) \
86219370Spst      { \
86319370Spst	growbuf_by_size (size); \
86419370Spst      } \
86519370Spst  } while (0);
86619370Spst
86719370Spst
86819370Spst/* Grow the static temp buffer if necessary, including allocating the first one
86919370Spst   on demand. */
87019370Spst
87119370Spststatic void
87219370Spstgrowbuf_by_size (count)
87319370Spst     int count;
87419370Spst{
87519370Spst  int growby;
87619370Spst
87719370Spst  growby = max (count, GROWBY_MIN_SIZE);
87819370Spst  tempbufsize += growby;
87919370Spst  if (tempbuf == NULL)
88019370Spst    tempbuf = (char *) malloc (tempbufsize);
88119370Spst  else
88219370Spst    tempbuf = (char *) realloc (tempbuf, tempbufsize);
88319370Spst}
88419370Spst
88519370Spst/* Blatantly ripped off from ch-exp.y. This routine recognizes F77
88619370Spst   string-literals.
88719370Spst
88819370Spst   Recognize a string literal.  A string literal is a nonzero sequence
88919370Spst   of characters enclosed in matching single quotes, except that
89019370Spst   a single character inside single quotes is a character literal, which
89119370Spst   we reject as a string literal.  To embed the terminator character inside
89219370Spst   a string, it is simply doubled (I.E. 'this''is''one''string') */
89319370Spst
89419370Spststatic int
89519370Spstmatch_string_literal ()
89619370Spst{
89719370Spst  char *tokptr = lexptr;
89819370Spst
89919370Spst  for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
90019370Spst    {
90119370Spst      CHECKBUF (1);
90219370Spst      if (*tokptr == *lexptr)
90319370Spst	{
90419370Spst	  if (*(tokptr + 1) == *lexptr)
90519370Spst	    tokptr++;
90619370Spst	  else
90719370Spst	    break;
90819370Spst	}
90919370Spst      tempbuf[tempbufindex++] = *tokptr;
91019370Spst    }
91119370Spst  if (*tokptr == '\0'					/* no terminator */
91219370Spst      || tempbufindex == 0)				/* no string */
91319370Spst    return 0;
91419370Spst  else
91519370Spst    {
91619370Spst      tempbuf[tempbufindex] = '\0';
91719370Spst      yylval.sval.ptr = tempbuf;
91819370Spst      yylval.sval.length = tempbufindex;
91919370Spst      lexptr = ++tokptr;
92019370Spst      return STRING_LITERAL;
92119370Spst    }
92219370Spst}
92319370Spst
92419370Spst/* Read one token, getting characters through lexptr.  */
92519370Spst
92619370Spststatic int
92719370Spstyylex ()
92819370Spst{
92919370Spst  int c;
93019370Spst  int namelen;
93119370Spst  unsigned int i,token;
93219370Spst  char *tokstart;
93319370Spst
93419370Spst retry:
935130803Smarcel
936130803Smarcel  prev_lexptr = lexptr;
937130803Smarcel
93819370Spst  tokstart = lexptr;
93919370Spst
94019370Spst  /* First of all, let us make sure we are not dealing with the
94119370Spst     special tokens .true. and .false. which evaluate to 1 and 0.  */
94219370Spst
94319370Spst  if (*lexptr == '.')
94419370Spst    {
94519370Spst      for (i = 0; boolean_values[i].name != NULL; i++)
94619370Spst	{
947130803Smarcel	  if (strncmp (tokstart, boolean_values[i].name,
948130803Smarcel		       strlen (boolean_values[i].name)) == 0)
94919370Spst	    {
95019370Spst	      lexptr += strlen (boolean_values[i].name);
95119370Spst	      yylval.lval = boolean_values[i].value;
95219370Spst	      return BOOLEAN_LITERAL;
95319370Spst	    }
95419370Spst	}
95519370Spst    }
95619370Spst
95719370Spst  /* See if it is a special .foo. operator */
95819370Spst
95919370Spst  for (i = 0; dot_ops[i].operator != NULL; i++)
960130803Smarcel    if (strncmp (tokstart, dot_ops[i].operator, strlen (dot_ops[i].operator)) == 0)
96119370Spst      {
96219370Spst	lexptr += strlen (dot_ops[i].operator);
96319370Spst	yylval.opcode = dot_ops[i].opcode;
96419370Spst	return dot_ops[i].token;
96519370Spst      }
96619370Spst
96719370Spst  switch (c = *tokstart)
96819370Spst    {
96919370Spst    case 0:
97019370Spst      return 0;
97119370Spst
97219370Spst    case ' ':
97319370Spst    case '\t':
97419370Spst    case '\n':
97519370Spst      lexptr++;
97619370Spst      goto retry;
97719370Spst
97819370Spst    case '\'':
97919370Spst      token = match_string_literal ();
98019370Spst      if (token != 0)
98119370Spst	return (token);
98219370Spst      break;
98319370Spst
98419370Spst    case '(':
98519370Spst      paren_depth++;
98619370Spst      lexptr++;
98719370Spst      return c;
98819370Spst
98919370Spst    case ')':
99019370Spst      if (paren_depth == 0)
99119370Spst	return 0;
99219370Spst      paren_depth--;
99319370Spst      lexptr++;
99419370Spst      return c;
99519370Spst
99619370Spst    case ',':
99719370Spst      if (comma_terminates && paren_depth == 0)
99819370Spst	return 0;
99919370Spst      lexptr++;
100019370Spst      return c;
100119370Spst
100219370Spst    case '.':
100319370Spst      /* Might be a floating point number.  */
100419370Spst      if (lexptr[1] < '0' || lexptr[1] > '9')
100519370Spst	goto symbol;		/* Nope, must be a symbol. */
100619370Spst      /* FALL THRU into number case.  */
100719370Spst
100819370Spst    case '0':
100919370Spst    case '1':
101019370Spst    case '2':
101119370Spst    case '3':
101219370Spst    case '4':
101319370Spst    case '5':
101419370Spst    case '6':
101519370Spst    case '7':
101619370Spst    case '8':
101719370Spst    case '9':
101819370Spst      {
101919370Spst        /* It's a number.  */
102019370Spst	int got_dot = 0, got_e = 0, got_d = 0, toktype;
1021130803Smarcel	char *p = tokstart;
102219370Spst	int hex = input_radix > 10;
102319370Spst
102419370Spst	if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
102519370Spst	  {
102619370Spst	    p += 2;
102719370Spst	    hex = 1;
102819370Spst	  }
102919370Spst	else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
103019370Spst	  {
103119370Spst	    p += 2;
103219370Spst	    hex = 0;
103319370Spst	  }
103419370Spst
103519370Spst	for (;; ++p)
103619370Spst	  {
103719370Spst	    if (!hex && !got_e && (*p == 'e' || *p == 'E'))
103819370Spst	      got_dot = got_e = 1;
103919370Spst	    else if (!hex && !got_d && (*p == 'd' || *p == 'D'))
104019370Spst	      got_dot = got_d = 1;
104119370Spst	    else if (!hex && !got_dot && *p == '.')
104219370Spst	      got_dot = 1;
104319370Spst	    else if (((got_e && (p[-1] == 'e' || p[-1] == 'E'))
104419370Spst		     || (got_d && (p[-1] == 'd' || p[-1] == 'D')))
104519370Spst		     && (*p == '-' || *p == '+'))
104619370Spst	      /* This is the sign of the exponent, not the end of the
104719370Spst		 number.  */
104819370Spst	      continue;
104919370Spst	    /* We will take any letters or digits.  parse_number will
105019370Spst	       complain if past the radix, or if L or U are not final.  */
105119370Spst	    else if ((*p < '0' || *p > '9')
105219370Spst		     && ((*p < 'a' || *p > 'z')
105319370Spst			 && (*p < 'A' || *p > 'Z')))
105419370Spst	      break;
105519370Spst	  }
105619370Spst	toktype = parse_number (tokstart, p - tokstart, got_dot|got_e|got_d,
105719370Spst				&yylval);
105819370Spst        if (toktype == ERROR)
105919370Spst          {
106019370Spst	    char *err_copy = (char *) alloca (p - tokstart + 1);
106119370Spst
106219370Spst	    memcpy (err_copy, tokstart, p - tokstart);
106319370Spst	    err_copy[p - tokstart] = 0;
106419370Spst	    error ("Invalid number \"%s\".", err_copy);
106519370Spst	  }
106619370Spst	lexptr = p;
106719370Spst	return toktype;
106819370Spst      }
106919370Spst
107019370Spst    case '+':
107119370Spst    case '-':
107219370Spst    case '*':
107319370Spst    case '/':
107419370Spst    case '%':
107519370Spst    case '|':
107619370Spst    case '&':
107719370Spst    case '^':
107819370Spst    case '~':
107919370Spst    case '!':
108019370Spst    case '@':
108119370Spst    case '<':
108219370Spst    case '>':
108319370Spst    case '[':
108419370Spst    case ']':
108519370Spst    case '?':
108619370Spst    case ':':
108719370Spst    case '=':
108819370Spst    case '{':
108919370Spst    case '}':
109019370Spst    symbol:
109119370Spst      lexptr++;
109219370Spst      return c;
109319370Spst    }
109419370Spst
109519370Spst  if (!(c == '_' || c == '$'
109619370Spst	|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
109719370Spst    /* We must have come across a bad character (e.g. ';').  */
109819370Spst    error ("Invalid character '%c' in expression.", c);
109919370Spst
110019370Spst  namelen = 0;
110119370Spst  for (c = tokstart[namelen];
110219370Spst       (c == '_' || c == '$' || (c >= '0' && c <= '9')
110319370Spst	|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
110419370Spst       c = tokstart[++namelen]);
110519370Spst
110619370Spst  /* The token "if" terminates the expression and is NOT
110719370Spst     removed from the input stream.  */
110819370Spst
110919370Spst  if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
111019370Spst    return 0;
111119370Spst
111219370Spst  lexptr += namelen;
111319370Spst
111419370Spst  /* Catch specific keywords.  */
111519370Spst
111619370Spst  for (i = 0; f77_keywords[i].operator != NULL; i++)
1117130803Smarcel    if (strncmp (tokstart, f77_keywords[i].operator,
1118130803Smarcel		 strlen(f77_keywords[i].operator)) == 0)
111919370Spst      {
112019370Spst	/* 	lexptr += strlen(f77_keywords[i].operator); */
112119370Spst	yylval.opcode = f77_keywords[i].opcode;
112219370Spst	return f77_keywords[i].token;
112319370Spst      }
112419370Spst
112519370Spst  yylval.sval.ptr = tokstart;
112619370Spst  yylval.sval.length = namelen;
112719370Spst
112819370Spst  if (*tokstart == '$')
112919370Spst    {
113019370Spst      write_dollar_variable (yylval.sval);
113119370Spst      return VARIABLE;
113219370Spst    }
113319370Spst
113419370Spst  /* Use token-type TYPENAME for symbols that happen to be defined
113519370Spst     currently as names of types; NAME for other symbols.
113619370Spst     The caller is not constrained to care about the distinction.  */
113719370Spst  {
113819370Spst    char *tmp = copy_name (yylval.sval);
113919370Spst    struct symbol *sym;
114019370Spst    int is_a_field_of_this = 0;
114119370Spst    int hextype;
114219370Spst
114319370Spst    sym = lookup_symbol (tmp, expression_context_block,
1144130803Smarcel			 VAR_DOMAIN,
114519370Spst			 current_language->la_language == language_cplus
114619370Spst			 ? &is_a_field_of_this : NULL,
114719370Spst			 NULL);
114819370Spst    if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
114919370Spst      {
115019370Spst	yylval.tsym.type = SYMBOL_TYPE (sym);
115119370Spst	return TYPENAME;
115219370Spst      }
115319370Spst    if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
115419370Spst      return TYPENAME;
115519370Spst
115619370Spst    /* Input names that aren't symbols but ARE valid hex numbers,
115719370Spst       when the input radix permits them, can be names or numbers
115819370Spst       depending on the parse.  Note we support radixes > 16 here.  */
115919370Spst    if (!sym
116019370Spst	&& ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
116119370Spst	    || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
116219370Spst      {
116319370Spst 	YYSTYPE newlval;	/* Its value is ignored.  */
116419370Spst	hextype = parse_number (tokstart, namelen, 0, &newlval);
116519370Spst	if (hextype == INT)
116619370Spst	  {
116719370Spst	    yylval.ssym.sym = sym;
116819370Spst	    yylval.ssym.is_a_field_of_this = is_a_field_of_this;
116919370Spst	    return NAME_OR_INT;
117019370Spst	  }
117119370Spst      }
117219370Spst
117319370Spst    /* Any other kind of symbol */
117419370Spst    yylval.ssym.sym = sym;
117519370Spst    yylval.ssym.is_a_field_of_this = is_a_field_of_this;
117619370Spst    return NAME;
117719370Spst  }
117819370Spst}
117919370Spst
118019370Spstvoid
118119370Spstyyerror (msg)
118219370Spst     char *msg;
118319370Spst{
1184130803Smarcel  if (prev_lexptr)
1185130803Smarcel    lexptr = prev_lexptr;
1186130803Smarcel
118719370Spst  error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
118819370Spst}
1189