/* YACC grammar for Chill expressions, for GDB.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
%{
#include "defs.h"
+#include <string.h>
+#include <ctype.h>
#include "expression.h"
#include "language.h"
#include "value.h"
#include "parser-defs.h"
#include "ch-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. */
-/* These MUST be included in any grammar file!!!! Please choose unique names!
- Note that this are a combined list of variables that can be produced
- by any one of bison, byacc, or yacc. */
#define yymaxdepth chill_maxdepth
#define yyparse chill_parse
#define yylex chill_lex
#define yypgo chill_pgo
#define yyact chill_act
#define yyexca chill_exca
-#define yyerrflag chill_errflag
-#define yynerrs chill_nerrs
+#define yyerrflag chill_errflag
+#define yynerrs chill_nerrs
#define yyps chill_ps
#define yypv chill_pv
#define yys chill_s
#define yy_yyv chill_yyv
#define yyval chill_val
#define yylloc chill_lloc
-#define yyss chill_yyss /* byacc */
-#define yyssp chill_yysp /* byacc */
-#define yyvs chill_yyvs /* byacc */
-#define yyvsp chill_yyvsp /* byacc */
+#define yyreds chill_reds /* With YYDEBUG defined */
+#define yytoks chill_toks /* With YYDEBUG defined */
+#define yylhs chill_yylhs
+#define yylen chill_yylen
+#define yydefred chill_yydefred
+#define yydgoto chill_yydgoto
+#define yysindex chill_yysindex
+#define yyrindex chill_yyrindex
+#define yygindex chill_yygindex
+#define yytable chill_yytable
+#define yycheck chill_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
static int
yylex PARAMS ((void));
void
yyerror PARAMS ((char *));
-int
-yyparse PARAMS ((void));
-
-/* #define YYDEBUG 1 */
-
%}
/* Although the yacc "value" of an expression is not used,
int *ivec;
}
-%token <voidval> FIXME
-
%token <typed_val> INTEGER_LITERAL
%token <ulval> BOOLEAN_LITERAL
%token <typed_val> CHARACTER_LITERAL
+%token <dval> FLOAT_LITERAL
%token <ssym> GENERAL_PROCEDURE_NAME
%token <ssym> LOCATION_NAME
-%token <voidval> SET_LITERAL
%token <voidval> EMPTINESS_LITERAL
-%token <voidval> CHARACTER_STRING_LITERAL
-%token <voidval> BIT_STRING_LITERAL
+%token <sval> CHARACTER_STRING_LITERAL
+%token <sval> BIT_STRING_LITERAL
+%token <tsym> TYPENAME
+%token <sval> FIELD_NAME
-%token <voidval> STRING
-%token <voidval> CONSTANT
%token <voidval> '.'
%token <voidval> ';'
%token <voidval> ':'
%token <voidval> NOT
%token <voidval> POINTER
%token <voidval> RECEIVE
-%token <voidval> SC
%token <voidval> '['
%token <voidval> ']'
%token <voidval> '('
%token <voidval> FI
%token <voidval> ELSIF
%token <voidval> ILLEGAL_TOKEN
+%token <voidval> NUM
+%token <voidval> PRED
+%token <voidval> SUCC
+%token <voidval> ABS
+%token <voidval> CARD
+%token <voidval> MAX_TOKEN
+%token <voidval> MIN_TOKEN
+%token <voidval> ADDR_TOKEN
+%token <voidval> SIZE
+%token <voidval> UPPER
+%token <voidval> LOWER
+%token <voidval> LENGTH
+%token <voidval> ARRAY
+
+/* Tokens which are not Chill tokens used in expressions, but rather GDB
+ specific things that we recognize in the same context as Chill tokens
+ (register names for example). */
+
+%token <lval> GDB_REGNAME /* Machine register name */
+%token <lval> GDB_LAST /* Value history */
+%token <ivar> GDB_VARIABLE /* Convenience variable */
+%token <voidval> GDB_ASSIGNMENT /* Assign value to somewhere */
-%type <voidval> location
%type <voidval> access_name
%type <voidval> primitive_value
-%type <voidval> location_contents
%type <voidval> value_name
%type <voidval> literal
%type <voidval> tuple
-%type <voidval> value_string_element
-%type <voidval> value_string_slice
-%type <voidval> value_array_element
-%type <voidval> value_array_slice
-%type <voidval> value_structure_field
+%type <voidval> slice
%type <voidval> expression_conversion
-%type <voidval> value_procedure_call
%type <voidval> value_built_in_routine_call
-%type <voidval> start_expression
-%type <voidval> zero_adic_operator
%type <voidval> parenthesised_expression
%type <voidval> value
-%type <voidval> undefined_value
%type <voidval> expression
%type <voidval> conditional_expression
%type <voidval> then_alternative
%type <voidval> else_alternative
-%type <voidval> sub_expression
-%type <voidval> value_case_alternative
%type <voidval> operand_0
%type <voidval> operand_1
%type <voidval> operand_2
%type <voidval> operand_4
%type <voidval> operand_5
%type <voidval> operand_6
-%type <voidval> integer_literal_expression
-%type <voidval> synonym_name
-%type <voidval> value_enumeration_name
-%type <voidval> value_do_with_name
-%type <voidval> value_receive_name
-%type <voidval> string_primitive_value
-%type <voidval> start_element
-%type <voidval> left_element
-%type <voidval> right_element
-%type <voidval> slice_size
-%type <voidval> array_primitive_value
%type <voidval> expression_list
-%type <voidval> lower_element
-%type <voidval> upper_element
-%type <voidval> first_element
-%type <voidval> structure_primitive_value
-%type <voidval> field_name
-%type <voidval> mode_name
-%type <voidval> boolean_expression
-%type <voidval> case_selector_list
-%type <voidval> subexpression
-%type <voidval> case_label_specification
-%type <voidval> buffer_location
+%type <tval> mode_argument
+%type <voidval> single_assignment_action
+%type <tsym> mode_name
+%type <lval> rparen
+
+/* Not implemented:
+%type <voidval> undefined_value
+%type <voidval> array_mode_name
+%type <voidval> string_mode_name
+%type <voidval> variant_structure_mode_name
+*/
%%
/* Z.200, 5.3.1 */
+start : value { }
+ | mode_name
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1.type);
+ write_exp_elt_opcode(OP_TYPE);}
+ ;
+
value : expression
- {
- $$ = 0; /* FIXME */
- }
+/*
| undefined_value
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-undefined_value : FIXME
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-/* Z.200, 4.2.1 */
-
-location : access_name
- {
- $$ = 0; /* FIXME */
- }
- | FIXME
- {
- $$ = 0; /* FIXME */
- }
+ { ??? }
+*/
;
/* Z.200, 4.2.2 */
access_name : LOCATION_NAME
{
write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
write_exp_elt_sym ($1.sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
- | FIXME
+ | GDB_LAST /* gdb specific */
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ($1);
+ write_exp_elt_opcode (OP_LAST);
}
- ;
-
-/* Z.200, 5.2.1 */
-
-primitive_value : location_contents
+ | GDB_REGNAME /* gdb specific */
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst ($1);
+ write_exp_elt_opcode (OP_REGISTER);
}
- | value_name
+ | GDB_VARIABLE /* gdb specific */
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern ($1);
+ write_exp_elt_opcode (OP_INTERNALVAR);
}
- | literal
+ ;
+
+/* Z.200, 4.2.8 */
+
+expression_list : expression
{
- $$ = 0; /* FIXME */
+ arglist_len = 1;
}
- | tuple
+ | expression_list ',' expression
{
- $$ = 0; /* FIXME */
+ arglist_len++;
}
- | value_string_element
+ ;
+
+maybe_expression_list: /* EMPTY */
{
- $$ = 0; /* FIXME */
+ arglist_len = 0;
}
- | value_string_slice
+ | expression_list
+ ;
+
+
+/* Z.200, 5.2.1 */
+
+primitive_value_lparen: primitive_value '('
+ /* This is to save the value of arglist_len
+ being accumulated for each dimension. */
+ { start_arglist (); }
+ ;
+
+rparen : ')'
+ { $$ = end_arglist (); }
+ ;
+
+primitive_value :
+ access_name
+ | primitive_value_lparen maybe_expression_list rparen
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst ($3);
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
}
- | value_array_element
- {
- $$ = 0; /* FIXME */
+ | primitive_value FIELD_NAME
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($2);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
}
- | value_array_slice
+ | primitive_value POINTER
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_IND);
}
- | value_structure_field
+ | primitive_value POINTER mode_name
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (lookup_pointer_type ($3.type));
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_opcode (UNOP_IND);
}
+ | value_name
+ | literal
+ | tuple
+ | slice
| expression_conversion
- {
- $$ = 0; /* FIXME */
- }
- | value_procedure_call
- {
- $$ = 0; /* FIXME */
- }
| value_built_in_routine_call
- {
- $$ = 0; /* FIXME */
- }
+/*
| start_expression
- {
- $$ = 0; /* FIXME */
- }
+ { ??? }
| zero_adic_operator
- {
- $$ = 0; /* FIXME */
- }
+ { ??? }
+*/
| parenthesised_expression
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-/* Z.200, 5.2.2 */
-
-location_contents: location
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 5.2.3 */
-value_name : synonym_name
- {
- $$ = 0; /* FIXME */
- }
- | value_enumeration_name
- {
- $$ = 0; /* FIXME */
- }
- | value_do_with_name
- {
- $$ = 0; /* FIXME */
- }
- | value_receive_name
- {
- $$ = 0; /* FIXME */
- }
- | GENERAL_PROCEDURE_NAME
+value_name : GENERAL_PROCEDURE_NAME
{
write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
write_exp_elt_sym ($1.sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
write_exp_elt_longcst ((LONGEST) ($1.val));
write_exp_elt_opcode (OP_LONG);
}
- | SET_LITERAL
+ | FLOAT_LITERAL
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE);
}
| EMPTINESS_LITERAL
{
- $$ = 0; /* FIXME */
+ struct type *void_ptr_type
+ = lookup_pointer_type (builtin_type_void);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (void_ptr_type);
+ write_exp_elt_longcst (0);
+ write_exp_elt_opcode (OP_LONG);
}
| CHARACTER_STRING_LITERAL
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
}
| BIT_STRING_LITERAL
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_BITSTRING);
+ write_exp_bitstring ($1);
+ write_exp_elt_opcode (OP_BITSTRING);
}
;
/* Z.200, 5.2.5 */
-tuple : FIXME
- {
- $$ = 0; /* FIXME */
- }
+tuple_element : expression
+ | named_record_element
;
-
-/* Z.200, 5.2.6 */
-
-value_string_element: string_primitive_value '(' start_element ')'
- {
- $$ = 0; /* FIXME */
+named_record_element: FIELD_NAME ',' named_record_element
+ { write_exp_elt_opcode (OP_LABELED);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_LABELED);
+ }
+ | FIELD_NAME ':' expression
+ { write_exp_elt_opcode (OP_LABELED);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_LABELED);
}
;
-/* Z.200, 5.2.7 */
-
-value_string_slice: string_primitive_value '(' left_element ':' right_element ')'
+tuple_elements : tuple_element
{
- $$ = 0; /* FIXME */
+ arglist_len = 1;
}
- | string_primitive_value '(' start_element UP slice_size ')'
+ | tuple_elements ',' tuple_element
{
- $$ = 0; /* FIXME */
+ arglist_len++;
}
;
-/* Z.200, 5.2.8 */
-
-value_array_element: array_primitive_value '(' expression_list ')'
- {
- $$ = 0; /* FIXME */
- }
+maybe_tuple_elements : tuple_elements
+ | /* EMPTY */
;
-/* Z.200, 5.2.9 */
-
-value_array_slice: array_primitive_value '(' lower_element ':' upper_element ')'
+tuple : '['
+ { start_arglist (); }
+ maybe_tuple_elements ']'
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
+ write_exp_elt_opcode (OP_ARRAY);
}
- | array_primitive_value '(' first_element UP slice_size '('
+ |
+ mode_name '['
+ { start_arglist (); }
+ maybe_tuple_elements ']'
{
- $$ = 0; /* FIXME */
- }
- ;
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
+ write_exp_elt_opcode (OP_ARRAY);
-/* Z.200, 5.2.10 */
-
-value_structure_field: structure_primitive_value '.' field_name
- {
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_opcode (UNOP_CAST);
}
;
-/* Z.200, 5.2.11 */
-expression_conversion: mode_name '(' expression ')'
- {
- $$ = 0; /* FIXME */
- }
- ;
+/* Z.200, 5.2.6 */
-/* Z.200, 5.2.12 */
-value_procedure_call: FIXME
+slice: primitive_value_lparen expression ':' expression rparen
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (TERNOP_SLICE);
}
- ;
-
-/* Z.200, 5.2.13 */
-
-value_built_in_routine_call: FIXME
+ | primitive_value_lparen expression UP expression rparen
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (TERNOP_SLICE_COUNT);
}
;
-/* Z.200, 5.2.14 */
-
-start_expression: FIXME
- {
- $$ = 0; /* FIXME */
- } /* Not in GNU-Chill */
- ;
-
-/* Z.200, 5.2.15 */
+/* Z.200, 5.2.11 */
-zero_adic_operator: FIXME
+expression_conversion: mode_name parenthesised_expression
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+ | ARRAY '(' ')' mode_name parenthesised_expression
+ /* This is pseudo-Chill, similar to C's '(TYPE[])EXPR'
+ which casts to an artificial array. */
+ {
+ struct type *range_type
+ = create_range_type ((struct type *) NULL,
+ builtin_type_int, 0, 0);
+ struct type *array_type
+ = create_array_type ((struct type *) NULL,
+ $4.type, range_type);
+ TYPE_ARRAY_UPPER_BOUND_TYPE(array_type)
+ = BOUND_CANNOT_BE_DETERMINED;
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (array_type);
+ write_exp_elt_opcode (UNOP_CAST);
}
;
/* Z.200, 5.2.16 */
parenthesised_expression: '(' expression ')'
- {
- $$ = 0; /* FIXME */
- }
;
/* Z.200, 5.3.2 */
expression : operand_0
- {
- $$ = 0; /* FIXME */
- }
+ | single_assignment_action
| conditional_expression
- {
- $$ = 0; /* FIXME */
- }
;
-conditional_expression : IF boolean_expression then_alternative else_alternative FI
- {
- $$ = 0; /* FIXME */
- }
- | CASE case_selector_list OF value_case_alternative '[' ELSE sub_expression ']' ESAC
- {
- $$ = 0; /* FIXME */
- }
+conditional_expression : IF expression then_alternative else_alternative FI
+ { write_exp_elt_opcode (TERNOP_COND); }
+/*
+ | CASE case_selector_list OF value_case_alternative ELSE expression ESAC
+ { error ("not implemented: CASE expression" }
+*/
;
-then_alternative: THEN subexpression
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-else_alternative: ELSE subexpression
- {
- $$ = 0; /* FIXME */
- }
- | ELSIF boolean_expression then_alternative else_alternative
- {
- $$ = 0; /* FIXME */
- }
- ;
-
-sub_expression : expression
- {
- $$ = 0; /* FIXME */
- }
+then_alternative: THEN expression
;
-value_case_alternative: case_label_specification ':' sub_expression ';'
- {
- $$ = 0; /* FIXME */
- }
+else_alternative: ELSE expression
+ | ELSIF expression then_alternative else_alternative
+ { write_exp_elt_opcode (TERNOP_COND); }
;
/* Z.200, 5.3.3 */
operand_0 : operand_1
- {
- $$ = 0; /* FIXME */
- }
| operand_0 LOGIOR operand_1
{
write_exp_elt_opcode (BINOP_BITWISE_IOR);
}
| operand_0 ORIF operand_1
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_LOGICAL_OR);
}
| operand_0 LOGXOR operand_1
{
/* Z.200, 5.3.4 */
operand_1 : operand_2
- {
- $$ = 0; /* FIXME */
- }
| operand_1 LOGAND operand_2
{
write_exp_elt_opcode (BINOP_BITWISE_AND);
}
| operand_1 ANDIF operand_2
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_LOGICAL_AND);
}
;
/* Z.200, 5.3.5 */
operand_2 : operand_3
- {
- $$ = 0; /* FIXME */
- }
| operand_2 '=' operand_3
{
write_exp_elt_opcode (BINOP_EQUAL);
}
| operand_2 IN operand_3
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_IN);
}
;
/* Z.200, 5.3.6 */
operand_3 : operand_4
- {
- $$ = 0; /* FIXME */
- }
| operand_3 '+' operand_4
{
write_exp_elt_opcode (BINOP_ADD);
}
| operand_3 SLASH_SLASH operand_4
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_CONCAT);
}
;
/* Z.200, 5.3.7 */
operand_4 : operand_5
- {
- $$ = 0; /* FIXME */
- }
| operand_4 '*' operand_5
{
write_exp_elt_opcode (BINOP_MUL);
}
| operand_4 MOD operand_5
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_MOD);
}
| operand_4 REM operand_5
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_REM);
}
;
/* Z.200, 5.3.8 */
operand_5 : operand_6
- {
- $$ = 0; /* FIXME */
- }
| '-' operand_6
{
write_exp_elt_opcode (UNOP_NEG);
{
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
}
- | '(' integer_literal_expression ')' operand_6
+ | parenthesised_expression literal
+/* We require the string operand to be a literal, to avoid some
+ nasty parsing ambiguities. */
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_CONCAT);
}
;
/* Z.200, 5.3.9 */
-operand_6 : POINTER location
- {
- $$ = 0; /* FIXME */
- }
- | RECEIVE buffer_location
+operand_6 : POINTER primitive_value
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
}
+ | RECEIVE expression
+ { error ("not implemented: RECEIVE expression"); }
| primitive_value
+ ;
+
+
+/* Z.200, 6.2 */
+
+single_assignment_action :
+ primitive_value GDB_ASSIGNMENT value
{
- $$ = 0; /* FIXME */
+ write_exp_elt_opcode (BINOP_ASSIGN);
}
;
+/* Z.200, 6.20.3 */
+
+value_built_in_routine_call :
+ NUM '(' expression ')'
+ {
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+ | PRED '(' expression ')'
+ { error ("not implemented: PRED builtin function"); }
+ | SUCC '(' expression ')'
+ { error ("not implemented: SUCC builtin function"); }
+ | ADDR_TOKEN '(' expression ')'
+ { write_exp_elt_opcode (UNOP_ADDR); }
+ | ABS '(' expression ')'
+ { error ("not implemented: ABS builtin function"); }
+ | CARD '(' expression ')'
+ { error ("not implemented: CARD builtin function"); }
+ | MAX_TOKEN '(' expression ')'
+ { error ("not implemented: MAX builtin function"); }
+ | MIN_TOKEN '(' expression ')'
+ { error ("not implemented: MIN builtin function"); }
+ | SIZE '(' expression ')'
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ | SIZE '(' mode_argument ')'
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ | LOWER '(' mode_argument ')'
+ { write_lower_upper_value (UNOP_LOWER, $3); }
+ | UPPER '(' mode_argument ')'
+ { write_lower_upper_value (UNOP_UPPER, $3); }
+ | LOWER '(' expression ')'
+ { write_exp_elt_opcode (UNOP_LOWER); }
+ | UPPER '(' expression ')'
+ { write_exp_elt_opcode (UNOP_UPPER); }
+ | LENGTH '(' expression ')'
+ { write_exp_elt_opcode (UNOP_LENGTH); }
+ ;
-/* Z.200, 12.4.3 */
-/* FIXME: For now we just accept only a single integer literal. */
-
-integer_literal_expression:
- INTEGER_LITERAL
+mode_argument : mode_name
{
- $$ = 0;
+ $$ = $1.type;
}
+/*
+ | array_mode_name '(' expression ')'
+ { ??? }
+ | string_mode_name '(' expression ')'
+ { ??? }
+ | variant_structure_mode_name '(' expression_list ')'
+ { ??? }
+*/
+ ;
-/* Things which still need productions... */
-synonym_name : FIXME { $$ = 0; }
-value_enumeration_name : FIXME { $$ = 0; }
-value_do_with_name : FIXME { $$ = 0; }
-value_receive_name : FIXME { $$ = 0; }
-string_primitive_value : FIXME { $$ = 0; }
-start_element : FIXME { $$ = 0; }
-left_element : FIXME { $$ = 0; }
-right_element : FIXME { $$ = 0; }
-slice_size : FIXME { $$ = 0; }
-array_primitive_value : FIXME { $$ = 0; }
-expression_list : FIXME { $$ = 0; }
-lower_element : FIXME { $$ = 0; }
-upper_element : FIXME { $$ = 0; }
-first_element : FIXME { $$ = 0; }
-structure_primitive_value: FIXME { $$ = 0; }
-field_name : FIXME { $$ = 0; }
-mode_name : FIXME { $$ = 0; }
-boolean_expression : FIXME { $$ = 0; }
-case_selector_list : FIXME { $$ = 0; }
-subexpression : FIXME { $$ = 0; }
-case_label_specification: FIXME { $$ = 0; }
-buffer_location : FIXME { $$ = 0; }
+mode_name : TYPENAME
+ ;
%%
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. */
+
+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);
+ }
+}
+
/* Try to consume a simple name string token. If successful, returns
a pointer to a nullbyte terminated copy of the name that can be used
in symbol table lookups. If not successful, returns NULL. */
{
char *tokptr = lexptr;
- if (isalpha (*tokptr))
+ if (isalpha (*tokptr) || *tokptr == '_')
{
+ char *result;
do {
tokptr++;
- } while (isalpha (*tokptr) || isdigit (*tokptr) || (*tokptr == '_'));
+ } while (isalnum (*tokptr) || (*tokptr == '_'));
yylval.sval.ptr = lexptr;
yylval.sval.length = tokptr - lexptr;
lexptr = tokptr;
- return (copy_name (yylval.sval));
+ result = copy_name (yylval.sval);
+ return result;
}
return (NULL);
}
while (*tokptr != '\0')
{
- temp = tolower (*tokptr);
+ temp = *tokptr;
+ if (isupper (temp))
+ temp = tolower (temp);
tokptr++;
switch (temp)
{
}
}
+/* If it wasn't for the fact that floating point values can contain '_'
+ characters, we could just let strtod do all the hard work by letting it
+ try to consume as much of the current token buffer as possible and
+ find a legal conversion. Unfortunately we need to filter out the '_'
+ characters before calling strtod, which we do by copying the other
+ legal chars to a local buffer to be converted. However since we also
+ need to keep track of where the last unconsumed character in the input
+ buffer is, we have transfer only as many characters as may compose a
+ legal floating point value. */
+
+static int
+match_float_literal ()
+{
+ char *tokptr = lexptr;
+ char *buf;
+ char *copy;
+ double dval;
+ extern double strtod ();
+
+ /* Make local buffer in which to build the string to convert. This is
+ required because underscores are valid in chill floating point numbers
+ but not in the string passed to strtod to convert. The string will be
+ no longer than our input string. */
+
+ copy = buf = (char *) alloca (strlen (tokptr) + 1);
+
+ /* Transfer all leading digits to the conversion buffer, discarding any
+ underscores. */
+
+ while (isdigit (*tokptr) || *tokptr == '_')
+ {
+ if (*tokptr != '_')
+ {
+ *copy++ = *tokptr;
+ }
+ tokptr++;
+ }
+
+ /* Now accept either a '.', or one of [eEdD]. Dot is legal regardless
+ of whether we found any leading digits, and we simply accept it and
+ continue on to look for the fractional part and/or exponent. One of
+ [eEdD] is legal only if we have seen digits, and means that there
+ is no fractional part. If we find neither of these, then this is
+ not a floating point number, so return failure. */
+
+ switch (*tokptr++)
+ {
+ case '.':
+ /* Accept and then look for fractional part and/or exponent. */
+ *copy++ = '.';
+ break;
+
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ if (copy == buf)
+ {
+ return (0);
+ }
+ *copy++ = 'e';
+ goto collect_exponent;
+ break;
+
+ default:
+ return (0);
+ break;
+ }
+
+ /* We found a '.', copy any fractional digits to the conversion buffer, up
+ to the first nondigit, non-underscore character. */
+
+ while (isdigit (*tokptr) || *tokptr == '_')
+ {
+ if (*tokptr != '_')
+ {
+ *copy++ = *tokptr;
+ }
+ tokptr++;
+ }
+
+ /* Look for an exponent, which must start with one of [eEdD]. If none
+ is found, jump directly to trying to convert what we have collected
+ so far. */
+
+ switch (*tokptr)
+ {
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ *copy++ = 'e';
+ tokptr++;
+ break;
+ default:
+ goto convert_float;
+ break;
+ }
+
+ /* Accept an optional '-' or '+' following one of [eEdD]. */
+
+ collect_exponent:
+ if (*tokptr == '+' || *tokptr == '-')
+ {
+ *copy++ = *tokptr++;
+ }
+
+ /* Now copy an exponent into the conversion buffer. Note that at the
+ moment underscores are *not* allowed in exponents. */
+
+ while (isdigit (*tokptr))
+ {
+ *copy++ = *tokptr++;
+ }
+
+ /* If we transfered any chars to the conversion buffer, try to interpret its
+ contents as a floating point value. If any characters remain, then we
+ must not have a valid floating point string. */
+
+ convert_float:
+ *copy = '\0';
+ if (copy != buf)
+ {
+ dval = strtod (buf, ©);
+ if (*copy == '\0')
+ {
+ yylval.dval = dval;
+ lexptr = tokptr;
+ return (FLOAT_LITERAL);
+ }
+ }
+ return (0);
+}
+
+/* Recognize a string literal. A string literal is a sequence
+ of characters enclosed in matching single or double 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 == 1 && *tokptr == '\'')) /* char literal */
+ {
+ return (0);
+ }
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return (CHARACTER_STRING_LITERAL);
+ }
+}
+
/* Recognize a character literal. A character literal is single character
or a control sequence, enclosed in single quotes. A control sequence
is a comma separated list of one or more integer literals, enclosed
As a GNU chill extension, the syntax C'xx' is also recognized as a
character literal, where xx is a hex value for the character.
+ Note that more than a single character, enclosed in single quotes, is
+ a string literal.
+
+ Also note that the control sequence form is not in GNU Chill since it
+ is ambiguous with the string literal form using single quotes. I.E.
+ is '^(7)' a character literal or a string literal. In theory it it
+ possible to tell by context, but GNU Chill doesn't accept the control
+ sequence form, so neither do we (for now the code is disabled).
+
Returns CHARACTER_LITERAL if a match is found.
*/
char *tokptr = lexptr;
int ival = 0;
- if ((tolower (*tokptr) == 'c') && (*(tokptr + 1) == '\''))
+ if ((*tokptr == 'c' || *tokptr == 'C') && (*(tokptr + 1) == '\''))
{
/* We have a GNU chill extension form, so skip the leading "C'",
decode the hex value, and then ensure that we have a trailing
if ((*tokptr == '^') && (*(tokptr + 1) == '('))
{
+#if 0 /* Disable, see note above. -fnf */
/* Match and decode a control sequence. Return zero if we don't
find a valid integer literal, or if the next unconsumed character
after the integer literal is not the trailing ')'.
{
return (0);
}
+#else
+ return (0);
+#endif
}
else
{
}
}
-#if 0
-static void convert_float ()
+/* Recognize a bit-string literal, as specified in Z.200 sec 5.2.4.8
+ Note that according to 5.2.4.8, a single "_" is also a valid bit-string
+ literal, however GNU-chill requires there to be at least one "digit"
+ in any bit-string literal. */
+
+static int
+match_bitstring_literal ()
{
- extern double strtod ();
- double d;
- char tmp[256];
- char *p = yytext, *p1 = tmp;
- char c;
-
- while (c = *p++)
+ register char *tokptr = lexptr;
+ int bitoffset = 0;
+ int bitcount = 0;
+ int bits_per_char;
+ int digit;
+
+ tempbufindex = 0;
+ CHECKBUF (1);
+ tempbuf[0] = 0;
+
+ /* Look for the required explicit base specifier. */
+
+ switch (*tokptr++)
{
- switch (c)
+ case 'b':
+ case 'B':
+ bits_per_char = 1;
+ break;
+ case 'o':
+ case 'O':
+ bits_per_char = 3;
+ break;
+ case 'h':
+ case 'H':
+ bits_per_char = 4;
+ break;
+ default:
+ return (0);
+ break;
+ }
+
+ /* Ensure that the character after the explicit base is a single quote. */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+
+ while (*tokptr != '\0' && *tokptr != '\'')
+ {
+ digit = *tokptr;
+ if (isupper (digit))
+ digit = tolower (digit);
+ tokptr++;
+ switch (digit)
{
- case '_':
+ case '_':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ digit -= '0';
break;
- case 'E':
- case 'd':
- case 'D':
- *p1++ = 'e';
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ digit -= 'a';
+ digit += 10;
break;
- default:
- *p1++ = c;
+ default:
+ return (0);
break;
}
+ if (digit >= 1 << bits_per_char)
+ {
+ /* Found something not in domain for current base. */
+ return (0);
+ }
+ else
+ {
+ /* Extract bits from digit, packing them into the bitstring byte. */
+ int k = TARGET_BYTE_ORDER == BIG_ENDIAN ? bits_per_char - 1 : 0;
+ for (; TARGET_BYTE_ORDER == BIG_ENDIAN ? k >= 0 : k < bits_per_char;
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? k-- : k++)
+ {
+ bitcount++;
+ if (digit & (1 << k))
+ {
+ tempbuf[tempbufindex] |=
+ (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ ? (1 << (HOST_CHAR_BIT - 1 - bitoffset))
+ : (1 << bitoffset);
+ }
+ bitoffset++;
+ if (bitoffset == HOST_CHAR_BIT)
+ {
+ bitoffset = 0;
+ tempbufindex++;
+ CHECKBUF(1);
+ tempbuf[tempbufindex] = 0;
+ }
+ }
+ }
}
- *p1 = '\0';
- d = strtod (tmp, &p1);
- if (*p1)
+
+ /* Verify that we consumed everything up to the trailing single quote,
+ and that we found some bits (IE not just underbars). */
+
+ if (*tokptr++ != '\'')
{
- /* add error handling here */
- ;
+ return (0);
+ }
+ else
+ {
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = bitcount;
+ lexptr = tokptr;
+ return (BIT_STRING_LITERAL);
}
- yylval.dval = d;
}
-#endif
-/* 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. */
+/* Recognize tokens that start with '$'. These include:
-/*** Needs some error checking for the float case ***/
+ $regname A native register name or a "standard
+ register name".
+ Return token GDB_REGNAME.
-struct token
-{
- char *operator;
- int token;
-};
+ $variable A convenience variable with a name chosen
+ by the user.
+ Return token GDB_VARIABLE.
+
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
+ Return GDB_LAST.
+
+ $$digits Value history with index <digits> relative
+ to the last value. I.E. $$0 is the last
+ value, $$1 is the one previous to that, $$2
+ is the one previous to $$1, etc.
+ Return token GDB_LAST.
+
+ $ | $0 | $$0 The last value in the value history.
+ Return token GDB_LAST.
+
+ $$ An abbreviation for the second to the last
+ value in the value history, I.E. $$1
+ Return token GDB_LAST.
+
+ Note that we currently assume that register names and convenience
+ variables follow the convention of starting with a letter or '_'.
-static const struct token tokentab5[] =
+ */
+
+static int
+match_dollar_tokens ()
{
- { "ANDIF", ANDIF }
-};
+ char *tokptr;
+ int regno;
+ int namelength;
+ int negate;
+ int ival;
+
+ /* We will always have a successful match, even if it is just for
+ a single '$', the abbreviation for $$0. So advance lexptr. */
+
+ tokptr = ++lexptr;
-static const struct token tokentab4[] =
+ if (*tokptr == '_' || isalpha (*tokptr))
+ {
+ /* Look for a match with a native register name, usually something
+ like "r0" for example. */
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ namelength = strlen (reg_names[regno]);
+ if (STREQN (tokptr, reg_names[regno], namelength)
+ && !isalnum (tokptr[namelength]))
+ {
+ yylval.lval = regno;
+ lexptr += namelength;
+ return (GDB_REGNAME);
+ }
+ }
+
+ /* Look for a match with a standard register name, usually something
+ like "pc", which gdb always recognizes as the program counter
+ regardless of what the native register name is. */
+
+ for (regno = 0; regno < num_std_regs; regno++)
+ {
+ namelength = strlen (std_regs[regno].name);
+ if (STREQN (tokptr, std_regs[regno].name, namelength)
+ && !isalnum (tokptr[namelength]))
+ {
+ yylval.lval = std_regs[regno].regnum;
+ lexptr += namelength;
+ return (GDB_REGNAME);
+ }
+ }
+
+ /* Attempt to match against a convenience variable. Note that
+ this will always succeed, because if no variable of that name
+ already exists, the lookup_internalvar will create one for us.
+ Also note that both lexptr and tokptr currently point to the
+ start of the input string we are trying to match, and that we
+ have already tested the first character for non-numeric, so we
+ don't have to treat it specially. */
+
+ while (*tokptr == '_' || isalnum (*tokptr))
+ {
+ tokptr++;
+ }
+ yylval.sval.ptr = lexptr;
+ yylval.sval.length = tokptr - lexptr;
+ yylval.ivar = lookup_internalvar (copy_name (yylval.sval));
+ lexptr = tokptr;
+ return (GDB_VARIABLE);
+ }
+
+ /* Since we didn't match against a register name or convenience
+ variable, our only choice left is a history value. */
+
+ if (*tokptr == '$')
+ {
+ negate = 1;
+ ival = 1;
+ tokptr++;
+ }
+ else
+ {
+ negate = 0;
+ ival = 0;
+ }
+
+ /* Attempt to decode more characters as an integer value giving
+ the index in the history list. If successful, the value will
+ overwrite ival (currently 0 or 1), and if not, ival will be
+ left alone, which is good since it is currently correct for
+ the '$' or '$$' case. */
+
+ decode_integer_literal (&ival, &tokptr);
+ yylval.lval = negate ? -ival : ival;
+ lexptr = tokptr;
+ return (GDB_LAST);
+}
+
+struct token
{
- { "ORIF", ORIF }
+ char *operator;
+ int token;
};
-static const struct token tokentab3[] =
+static const struct token idtokentab[] =
{
- { "NOT", NOT },
- { "XOR", LOGXOR },
- { "AND", LOGAND }
+ { "array", ARRAY },
+ { "length", LENGTH },
+ { "lower", LOWER },
+ { "upper", UPPER },
+ { "andif", ANDIF },
+ { "pred", PRED },
+ { "succ", SUCC },
+ { "card", CARD },
+ { "size", SIZE },
+ { "orif", ORIF },
+ { "num", NUM },
+ { "abs", ABS },
+ { "max", MAX_TOKEN },
+ { "min", MIN_TOKEN },
+ { "mod", MOD },
+ { "rem", REM },
+ { "not", NOT },
+ { "xor", LOGXOR },
+ { "and", LOGAND },
+ { "in", IN },
+ { "or", LOGIOR },
+ { "up", UP },
+ { "addr", ADDR_TOKEN },
+ { "null", EMPTINESS_LITERAL }
};
static const struct token tokentab2[] =
{
+ { ":=", GDB_ASSIGNMENT },
{ "//", SLASH_SLASH },
+ { "->", POINTER },
{ "/=", NOTEQUAL },
{ "<=", LEQ },
- { ">=", GTR },
- { "IN", IN },
- { "OR", LOGIOR }
+ { ">=", GTR }
};
/* Read one token, getting characters through lexptr. */
{
unsigned int i;
int token;
- char *simplename;
+ char *inputname;
struct symbol *sym;
/* Skip over any leading whitespace. */
{
case '\0':
return (0);
- case '.':
+ case ',':
case '=':
- case ':':
case ';':
case '!':
case '+':
- case '-':
case '*':
- case '/':
case '(':
case ')':
case '[':
return (*lexptr++);
}
/* Look for characters which start a particular kind of multicharacter
- token, such as a character literal. */
+ token, such as a character literal, register name, convenience
+ variable name, string literal, etc. */
switch (*lexptr)
{
+ case '\'':
+ case '\"':
+ /* First try to match a string literal, which is any
+ sequence of characters enclosed in matching single or double
+ quotes, except that a single character inside single quotes
+ is a character literal, so we have to catch that case also. */
+ token = match_string_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ if (*lexptr == '\'')
+ {
+ token = match_character_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ }
+ break;
case 'C':
case 'c':
- case '\'':
token = match_character_literal ();
if (token != 0)
{
return (token);
}
break;
+ case '$':
+ token = match_dollar_tokens ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ break;
}
- /* See if it is a special token of length 5. */
- for (i = 0; i < sizeof (tokentab5) / sizeof (tokentab5[0]); i++)
- {
- if (strncmp (lexptr, tokentab5[i].operator, 5) == 0)
- {
- lexptr += 5;
- return (tokentab5[i].token);
- }
- }
- /* See if it is a special token of length 4. */
- for (i = 0; i < sizeof (tokentab4) / sizeof (tokentab4[0]); i++)
- {
- if (strncmp (lexptr, tokentab4[i].operator, 4) == 0)
- {
- lexptr += 4;
- return (tokentab4[i].token);
- }
- }
- /* See if it is a special token of length 3. */
- for (i = 0; i < sizeof (tokentab3) / sizeof (tokentab3[0]); i++)
- {
- if (strncmp (lexptr, tokentab3[i].operator, 3) == 0)
- {
- lexptr += 3;
- return (tokentab3[i].token);
- }
- }
/* See if it is a special token of length 2. */
for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
{
- if (strncmp (lexptr, tokentab2[i].operator, 2) == 0)
+ if (STREQN (lexptr, tokentab2[i].operator, 2))
{
lexptr += 2;
return (tokentab2[i].token);
would already have found it. */
switch (*lexptr)
{
+ case '-':
+ case ':':
case '/':
case '<':
case '>':
return (*lexptr++);
}
- /* Look for other special tokens. */
- if (strncmp (lexptr, "TRUE", 4) == 0) /* FIXME: What about lowercase? */
+ /* Look for a float literal before looking for an integer literal, so
+ we match as much of the input stream as possible. */
+ token = match_float_literal ();
+ if (token != 0)
{
- yylval.ulval = 1;
- lexptr += 4;
- return (BOOLEAN_LITERAL);
+ return (token);
}
- if (strncmp (lexptr, "FALSE", 5) == 0) /* FIXME: What about lowercase? */
+ token = match_bitstring_literal ();
+ if (token != 0)
{
- yylval.ulval = 0;
- lexptr += 5;
- return (BOOLEAN_LITERAL);
+ return (token);
}
token = match_integer_literal ();
if (token != 0)
the token from lexptr, so we can't back out if we later find that
we can't classify what sort of name it is. */
- simplename = match_simple_name_string ();
- if (simplename != NULL)
+ inputname = match_simple_name_string ();
+
+ if (inputname != NULL)
{
- sym = lookup_symbol (simplename, expression_context_block,
+ char *simplename = (char*) alloca (strlen (inputname) + 1);
+
+ char *dptr = simplename, *sptr = inputname;
+ for (; *sptr; sptr++)
+ *dptr++ = isupper (*sptr) ? tolower(*sptr) : *sptr;
+ *dptr = '\0';
+
+ /* See if it is a reserved identifier. */
+ for (i = 0; i < sizeof (idtokentab) / sizeof (idtokentab[0]); i++)
+ {
+ if (STREQ (simplename, idtokentab[i].operator))
+ {
+ return (idtokentab[i].token);
+ }
+ }
+
+ /* Look for other special tokens. */
+ if (STREQ (simplename, "true"))
+ {
+ yylval.ulval = 1;
+ return (BOOLEAN_LITERAL);
+ }
+ if (STREQ (simplename, "false"))
+ {
+ yylval.ulval = 0;
+ return (BOOLEAN_LITERAL);
+ }
+
+ sym = lookup_symbol (inputname, expression_context_block,
VAR_NAMESPACE, (int *) NULL,
(struct symtab **) NULL);
+ if (sym == NULL && strcmp (inputname, simplename) != 0)
+ {
+ sym = lookup_symbol (simplename, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ }
if (sym != NULL)
{
yylval.ssym.stoken.ptr = NULL;
case LOC_STATIC:
/* Found a global or local static variable. */
return (LOCATION_NAME);
- case LOC_UNDEF:
- case LOC_CONST:
case LOC_REGISTER:
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
case LOC_LOCAL:
- case LOC_TYPEDEF:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ if (innermost_block == NULL
+ || contained_in (block_found, innermost_block))
+ {
+ innermost_block = block_found;
+ }
+ return (LOCATION_NAME);
+ break;
+ case LOC_CONST:
case LOC_LABEL:
+ return (LOCATION_NAME);
+ break;
+ case LOC_TYPEDEF:
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ case LOC_UNDEF:
case LOC_CONST_BYTES:
- case LOC_LOCAL_ARG:
+ case LOC_OPTIMIZED_OUT:
+ error ("Symbol \"%s\" names no location.", inputname);
break;
}
}
}
else
{
- error ("No symbol \"%s\" in current context.", simplename);
+ error ("No symbol \"%s\" in current context.", inputname);
}
}
+ /* Catch single character tokens which are not part of some
+ longer token. */
+
+ switch (*lexptr)
+ {
+ case '.': /* Not float for example. */
+ lexptr++;
+ while (isspace (*lexptr)) lexptr++;
+ inputname = match_simple_name_string ();
+ if (!inputname)
+ return '.';
+ return FIELD_NAME;
+ }
+
return (ILLEGAL_TOKEN);
}
+void
+write_lower_upper_value (opcode, type)
+ enum exp_opcode opcode; /* Either UNOP_LOWER or UNOP_UPPER */
+ struct type *type;
+{
+ extern LONGEST type_lower_upper ();
+ struct type *result_type;
+ LONGEST val = type_lower_upper (opcode, type, &result_type);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (result_type);
+ write_exp_elt_longcst (val);
+ write_exp_elt_opcode (OP_LONG);
+}
+
void
yyerror (msg)
- char *msg; /* unused */
+ char *msg;
{
- printf ("Parsing: %s\n", lexptr);
- if (yychar < 256)
- {
- error ("Invalid syntax in expression near character '%c'.", yychar);
- }
- else
- {
- error ("Invalid syntax in expression");
- }
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
}