#define NOTUI
#include "defs.h"
#include "gdb_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"
#include "symfile.h"
#include "objfiles.h"
#ifdef __GNUC__
#define INLINE __inline__
#endif
typedef union
{
LONGEST lval;
ULONGEST ulval;
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;
}
YYSTYPE;
enum ch_terminal
{
END_TOKEN = 0,
OPEN_PAREN = '(',
TOKEN_NOT_READ = 999,
INTEGER_LITERAL,
BOOLEAN_LITERAL,
CHARACTER_LITERAL,
FLOAT_LITERAL,
GENERAL_PROCEDURE_NAME,
LOCATION_NAME,
EMPTINESS_LITERAL,
CHARACTER_STRING_LITERAL,
BIT_STRING_LITERAL,
TYPENAME,
DOT_FIELD_NAME,
CASE,
OF,
ESAC,
LOGIOR,
ORIF,
LOGXOR,
LOGAND,
ANDIF,
NOTEQUAL,
GEQ,
LEQ,
IN,
SLASH_SLASH,
MOD,
REM,
NOT,
POINTER,
RECEIVE,
UP,
IF,
THEN,
ELSE,
FI,
ELSIF,
ILLEGAL_TOKEN,
NUM,
PRED,
SUCC,
ABS,
CARD,
MAX_TOKEN,
MIN_TOKEN,
ADDR_TOKEN,
SIZE,
UPPER,
LOWER,
LENGTH,
ARRAY,
GDB_VARIABLE,
GDB_ASSIGNMENT
};
static void write_lower_upper_value (enum exp_opcode, struct type *);
static enum ch_terminal match_bitstring_literal (void);
static enum ch_terminal match_integer_literal (void);
static enum ch_terminal match_character_literal (void);
static enum ch_terminal match_string_literal (void);
static enum ch_terminal match_float_literal (void);
static int decode_integer_literal (LONGEST *, char **);
static int decode_integer_value (int, char **, LONGEST *);
static char *match_simple_name_string (void);
static void growbuf_by_size (int);
static void parse_case_label (void);
static void parse_untyped_expr (void);
static void parse_if_expression (void);
static void parse_if_expression_body (void);
static void parse_else_alternative (void);
static void parse_then_alternative (void);
static void parse_expr (void);
static void parse_operand0 (void);
static void parse_operand1 (void);
static void parse_operand2 (void);
static void parse_operand3 (void);
static void parse_operand4 (void);
static void parse_operand5 (void);
static void parse_operand6 (void);
static void parse_primval (void);
static void parse_tuple (struct type *);
static void parse_opt_element_list (struct type *);
static void parse_tuple_element (struct type *);
static void parse_named_record_element (void);
static void parse_call (void);
static struct type *parse_mode_or_normal_call (void);
#if 0
static struct type *parse_mode_call (void);
#endif
static void parse_unary_call (void);
static int parse_opt_untyped_expr (void);
static int expect (enum ch_terminal, char *);
static enum ch_terminal ch_lex (void);
INLINE static enum ch_terminal PEEK_TOKEN (void);
static enum ch_terminal peek_token_ (int);
static void forward_token_ (void);
static void require (enum ch_terminal);
static int check_token (enum ch_terminal);
#define MAX_LOOK_AHEAD 2
static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD + 1] =
{
TOKEN_NOT_READ, TOKEN_NOT_READ, TOKEN_NOT_READ};
static YYSTYPE yylval;
static YYSTYPE val_buffer[MAX_LOOK_AHEAD + 1];
INLINE static enum ch_terminal
PEEK_TOKEN (void)
{
if (terminal_buffer[0] == TOKEN_NOT_READ)
{
terminal_buffer[0] = ch_lex ();
val_buffer[0] = yylval;
}
return terminal_buffer[0];
}
#define PEEK_LVAL() val_buffer[0]
#define PEEK_TOKEN1() peek_token_(1)
#define PEEK_TOKEN2() peek_token_(2)
static enum ch_terminal
peek_token_ (int i)
{
if (i > MAX_LOOK_AHEAD)
internal_error (__FILE__, __LINE__,
"too much lookahead");
if (terminal_buffer[i] == TOKEN_NOT_READ)
{
terminal_buffer[i] = ch_lex ();
val_buffer[i] = yylval;
}
return terminal_buffer[i];
}
#if 0
static void
pushback_token (enum ch_terminal code, YYSTYPE node)
{
int i;
if (terminal_buffer[MAX_LOOK_AHEAD] != TOKEN_NOT_READ)
internal_error (__FILE__, __LINE__,
"cannot pushback token");
for (i = MAX_LOOK_AHEAD; i > 0; i--)
{
terminal_buffer[i] = terminal_buffer[i - 1];
val_buffer[i] = val_buffer[i - 1];
}
terminal_buffer[0] = code;
val_buffer[0] = node;
}
#endif
static void
forward_token_ (void)
{
int i;
for (i = 0; i < MAX_LOOK_AHEAD; i++)
{
terminal_buffer[i] = terminal_buffer[i + 1];
val_buffer[i] = val_buffer[i + 1];
}
terminal_buffer[MAX_LOOK_AHEAD] = TOKEN_NOT_READ;
}
#define FORWARD_TOKEN() forward_token_()
static void
require (enum ch_terminal token)
{
if (PEEK_TOKEN () != token)
{
internal_error (__FILE__, __LINE__,
"expected token %d", (int) token);
}
FORWARD_TOKEN ();
}
static int
check_token (enum ch_terminal token)
{
if (PEEK_TOKEN () != token)
return 0;
FORWARD_TOKEN ();
return 1;
}
static int
expect (enum ch_terminal token, char *message)
{
if (PEEK_TOKEN () != token)
{
if (message)
error (message);
else if (token < 256)
error ("syntax error - expected a '%c' here \"%s\"", token, lexptr);
else
error ("syntax error");
return 0;
}
else
FORWARD_TOKEN ();
return 1;
}
#if 0
static tree
parse_opt_name_string (int allow_all)
{
int token = PEEK_TOKEN ();
tree name;
if (token != NAME)
{
if (token == ALL && allow_all)
{
FORWARD_TOKEN ();
return ALL_POSTFIX;
}
return NULL_TREE;
}
name = PEEK_LVAL ();
for (;;)
{
FORWARD_TOKEN ();
token = PEEK_TOKEN ();
if (token != '!')
return name;
FORWARD_TOKEN ();
token = PEEK_TOKEN ();
if (token == ALL && allow_all)
return get_identifier3 (IDENTIFIER_POINTER (name), "!", "*");
if (token != NAME)
{
if (pass == 1)
error ("'%s!' is not followed by an identifier",
IDENTIFIER_POINTER (name));
return name;
}
name = get_identifier3 (IDENTIFIER_POINTER (name),
"!", IDENTIFIER_POINTER (PEEK_LVAL ()));
}
}
static tree
parse_simple_name_string (void)
{
int token = PEEK_TOKEN ();
tree name;
if (token != NAME)
{
error ("expected a name here");
return error_mark_node;
}
name = PEEK_LVAL ();
FORWARD_TOKEN ();
return name;
}
static tree
parse_name_string (void)
{
tree name = parse_opt_name_string (0);
if (name)
return name;
if (pass == 1)
error ("expected a name string here");
return error_mark_node;
}
static tree
parse_name (void)
{
tree name = parse_name_string ();
if (pass == 1 || ignoring)
return name;
else
{
tree decl = lookup_name (name);
if (decl == NULL_TREE)
{
error ("`%s' undeclared", IDENTIFIER_POINTER (name));
return error_mark_node;
}
else if (TREE_CODE (TREE_TYPE (decl)) == ERROR_MARK)
return error_mark_node;
else if (TREE_CODE (decl) == CONST_DECL)
return DECL_INITIAL (decl);
else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
return convert_from_reference (decl);
else
return decl;
}
}
#endif
#if 0
static void
pushback_paren_expr (tree expr)
{
if (pass == 1 && !ignoring)
expr = build1 (PAREN_EXPR, NULL_TREE, expr);
pushback_token (EXPR, expr);
}
#endif
static void
parse_case_label (void)
{
if (check_token (ELSE))
error ("ELSE in tuples labels not implemented");
parse_expr ();
if (check_token (':'))
{
parse_expr ();
write_exp_elt_opcode (BINOP_RANGE);
}
}
static int
parse_opt_untyped_expr (void)
{
switch (PEEK_TOKEN ())
{
case ',':
case ':':
case ')':
return 0;
default:
parse_untyped_expr ();
return 1;
}
}
static void
parse_unary_call (void)
{
FORWARD_TOKEN ();
expect ('(', NULL);
parse_expr ();
expect (')', NULL);
}
#if 0
static struct type *
parse_mode_call (void)
{
struct type *type;
FORWARD_TOKEN ();
expect ('(', NULL);
if (PEEK_TOKEN () != TYPENAME)
error ("expect MODENAME here `%s'", lexptr);
type = PEEK_LVAL ().tsym.type;
FORWARD_TOKEN ();
expect (')', NULL);
return type;
}
#endif
static struct type *
parse_mode_or_normal_call (void)
{
struct type *type;
FORWARD_TOKEN ();
expect ('(', NULL);
if (PEEK_TOKEN () == TYPENAME)
{
type = PEEK_LVAL ().tsym.type;
FORWARD_TOKEN ();
}
else
{
parse_expr ();
type = NULL;
}
expect (')', NULL);
return type;
}
static void
parse_call (void)
{
int arg_count;
require ('(');
start_arglist ();
if (parse_opt_untyped_expr ())
{
int tok = PEEK_TOKEN ();
arglist_len = 1;
if (tok == UP || tok == ':')
{
FORWARD_TOKEN ();
parse_expr ();
expect (')', "expected ')' to terminate slice");
end_arglist ();
write_exp_elt_opcode (tok == UP ? TERNOP_SLICE_COUNT
: TERNOP_SLICE);
return;
}
while (check_token (','))
{
parse_untyped_expr ();
arglist_len++;
}
}
else
arglist_len = 0;
expect (')', NULL);
arg_count = end_arglist ();
write_exp_elt_opcode (MULTI_SUBSCRIPT);
write_exp_elt_longcst (arg_count);
write_exp_elt_opcode (MULTI_SUBSCRIPT);
}
static void
parse_named_record_element (void)
{
struct stoken label;
char buf[256];
label = PEEK_LVAL ().sval;
sprintf (buf, "expected a field name here `%s'", lexptr);
expect (DOT_FIELD_NAME, buf);
if (check_token (','))
parse_named_record_element ();
else if (check_token (':'))
parse_expr ();
else
error ("syntax error near `%s' in named record tuple element", lexptr);
write_exp_elt_opcode (OP_LABELED);
write_exp_string (label);
write_exp_elt_opcode (OP_LABELED);
}
static void
parse_tuple_element (struct type *type)
{
if (PEEK_TOKEN () == DOT_FIELD_NAME)
{
parse_named_record_element ();
return;
}
if (check_token ('('))
{
if (check_token ('*'))
{
expect (')', "missing ')' after '*' case label list");
if (type)
{
if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
{
struct type *range_type = TYPE_FIELD_TYPE (type, 0);
LONGEST low_bound, high_bound;
if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
error ("cannot determine bounds for (*)");
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (range_type);
write_exp_elt_longcst (low_bound);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (range_type);
write_exp_elt_longcst (high_bound);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (BINOP_RANGE);
}
else
error ("(*) in invalid context");
}
else
error ("(*) only possible with modename in front of tuple (mode[..])");
}
else
{
parse_case_label ();
while (check_token (','))
{
parse_case_label ();
write_exp_elt_opcode (BINOP_COMMA);
}
expect (')', NULL);
}
}
else
parse_untyped_expr ();
if (check_token (':'))
{
parse_untyped_expr ();
write_exp_elt_opcode (BINOP_RANGE);
}
}
static void
parse_opt_element_list (struct type *type)
{
arglist_len = 0;
if (PEEK_TOKEN () == ']')
return;
for (;;)
{
parse_tuple_element (type);
arglist_len++;
if (PEEK_TOKEN () == ']')
break;
if (!check_token (','))
error ("bad syntax in tuple");
}
}
static void
parse_tuple (struct type *mode)
{
struct type *type;
if (mode)
type = check_typedef (mode);
else
type = 0;
require ('[');
start_arglist ();
parse_opt_element_list (type);
expect (']', "missing ']' after tuple");
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);
if (type)
{
if (TYPE_CODE (type) != TYPE_CODE_ARRAY
&& TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_SET)
error ("invalid tuple mode");
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (mode);
write_exp_elt_opcode (UNOP_CAST);
}
}
static void
parse_primval (void)
{
struct type *type;
enum exp_opcode op;
char *op_name;
switch (PEEK_TOKEN ())
{
case INTEGER_LITERAL:
case CHARACTER_LITERAL:
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (PEEK_LVAL ().typed_val.type);
write_exp_elt_longcst (PEEK_LVAL ().typed_val.val);
write_exp_elt_opcode (OP_LONG);
FORWARD_TOKEN ();
break;
case BOOLEAN_LITERAL:
write_exp_elt_opcode (OP_BOOL);
write_exp_elt_longcst ((LONGEST) PEEK_LVAL ().ulval);
write_exp_elt_opcode (OP_BOOL);
FORWARD_TOKEN ();
break;
case FLOAT_LITERAL:
write_exp_elt_opcode (OP_DOUBLE);
write_exp_elt_type (builtin_type_double);
write_exp_elt_dblcst (PEEK_LVAL ().dval);
write_exp_elt_opcode (OP_DOUBLE);
FORWARD_TOKEN ();
break;
case EMPTINESS_LITERAL:
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (lookup_pointer_type (builtin_type_void));
write_exp_elt_longcst (0);
write_exp_elt_opcode (OP_LONG);
FORWARD_TOKEN ();
break;
case CHARACTER_STRING_LITERAL:
write_exp_elt_opcode (OP_STRING);
write_exp_string (PEEK_LVAL ().sval);
write_exp_elt_opcode (OP_STRING);
FORWARD_TOKEN ();
break;
case BIT_STRING_LITERAL:
write_exp_elt_opcode (OP_BITSTRING);
write_exp_bitstring (PEEK_LVAL ().sval);
write_exp_elt_opcode (OP_BITSTRING);
FORWARD_TOKEN ();
break;
case ARRAY:
FORWARD_TOKEN ();
expect ('(', NULL);
expect (')', NULL);
if (PEEK_TOKEN () != TYPENAME)
error ("missing MODENAME after ARRAY()");
type = PEEK_LVAL ().tsym.type;
FORWARD_TOKEN ();
expect ('(', NULL);
parse_expr ();
expect (')', "missing right parenthesis");
type = create_array_type ((struct type *) NULL, type,
create_range_type ((struct type *) NULL,
builtin_type_int, 0, 0));
TYPE_ARRAY_UPPER_BOUND_TYPE (type) = BOUND_CANNOT_BE_DETERMINED;
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (type);
write_exp_elt_opcode (UNOP_CAST);
break;
#if 0
case CONST:
case EXPR:
val = PEEK_LVAL ();
FORWARD_TOKEN ();
break;
#endif
case '(':
FORWARD_TOKEN ();
parse_expr ();
expect (')', "missing right parenthesis");
break;
case '[':
parse_tuple (NULL);
break;
case GENERAL_PROCEDURE_NAME:
case LOCATION_NAME:
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_block (NULL);
write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
write_exp_elt_opcode (OP_VAR_VALUE);
FORWARD_TOKEN ();
break;
case GDB_VARIABLE:
FORWARD_TOKEN ();
break;
case NUM:
parse_unary_call ();
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (builtin_type_int);
write_exp_elt_opcode (UNOP_CAST);
break;
case CARD:
parse_unary_call ();
write_exp_elt_opcode (UNOP_CARD);
break;
case MAX_TOKEN:
parse_unary_call ();
write_exp_elt_opcode (UNOP_CHMAX);
break;
case MIN_TOKEN:
parse_unary_call ();
write_exp_elt_opcode (UNOP_CHMIN);
break;
case PRED:
op_name = "PRED";
goto unimplemented_unary_builtin;
case SUCC:
op_name = "SUCC";
goto unimplemented_unary_builtin;
case ABS:
op_name = "ABS";
goto unimplemented_unary_builtin;
unimplemented_unary_builtin:
parse_unary_call ();
error ("not implemented: %s builtin function", op_name);
break;
case ADDR_TOKEN:
parse_unary_call ();
write_exp_elt_opcode (UNOP_ADDR);
break;
case SIZE:
type = parse_mode_or_normal_call ();
if (type)
{
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
CHECK_TYPEDEF (type);
write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (type));
write_exp_elt_opcode (OP_LONG);
}
else
write_exp_elt_opcode (UNOP_SIZEOF);
break;
case LOWER:
op = UNOP_LOWER;
goto lower_upper;
case UPPER:
op = UNOP_UPPER;
goto lower_upper;
lower_upper:
type = parse_mode_or_normal_call ();
write_lower_upper_value (op, type);
break;
case LENGTH:
parse_unary_call ();
write_exp_elt_opcode (UNOP_LENGTH);
break;
case TYPENAME:
type = PEEK_LVAL ().tsym.type;
FORWARD_TOKEN ();
switch (PEEK_TOKEN ())
{
case '[':
parse_tuple (type);
break;
case '(':
FORWARD_TOKEN ();
parse_expr ();
expect (')', "missing right parenthesis");
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (type);
write_exp_elt_opcode (UNOP_CAST);
break;
default:
error ("typename in invalid context");
}
break;
default:
error ("invalid expression syntax at `%s'", lexptr);
}
for (;;)
{
switch (PEEK_TOKEN ())
{
case DOT_FIELD_NAME:
write_exp_elt_opcode (STRUCTOP_STRUCT);
write_exp_string (PEEK_LVAL ().sval);
write_exp_elt_opcode (STRUCTOP_STRUCT);
FORWARD_TOKEN ();
continue;
case POINTER:
FORWARD_TOKEN ();
if (PEEK_TOKEN () == TYPENAME)
{
type = PEEK_LVAL ().tsym.type;
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (lookup_pointer_type (type));
write_exp_elt_opcode (UNOP_CAST);
FORWARD_TOKEN ();
}
write_exp_elt_opcode (UNOP_IND);
continue;
case OPEN_PAREN:
parse_call ();
continue;
case CHARACTER_STRING_LITERAL:
case CHARACTER_LITERAL:
case BIT_STRING_LITERAL:
parse_primval ();
write_exp_elt_opcode (MULTI_SUBSCRIPT);
write_exp_elt_longcst (1);
write_exp_elt_opcode (MULTI_SUBSCRIPT);
continue;
case END_TOKEN:
case TOKEN_NOT_READ:
case INTEGER_LITERAL:
case BOOLEAN_LITERAL:
case FLOAT_LITERAL:
case GENERAL_PROCEDURE_NAME:
case LOCATION_NAME:
case EMPTINESS_LITERAL:
case TYPENAME:
case CASE:
case OF:
case ESAC:
case LOGIOR:
case ORIF:
case LOGXOR:
case LOGAND:
case ANDIF:
case NOTEQUAL:
case GEQ:
case LEQ:
case IN:
case SLASH_SLASH:
case MOD:
case REM:
case NOT:
case RECEIVE:
case UP:
case IF:
case THEN:
case ELSE:
case FI:
case ELSIF:
case ILLEGAL_TOKEN:
case NUM:
case PRED:
case SUCC:
case ABS:
case CARD:
case MAX_TOKEN:
case MIN_TOKEN:
case ADDR_TOKEN:
case SIZE:
case UPPER:
case LOWER:
case LENGTH:
case ARRAY:
case GDB_VARIABLE:
case GDB_ASSIGNMENT:
break;
}
break;
}
return;
}
static void
parse_operand6 (void)
{
if (check_token (RECEIVE))
{
parse_primval ();
error ("not implemented: RECEIVE expression");
}
else if (check_token (POINTER))
{
parse_primval ();
write_exp_elt_opcode (UNOP_ADDR);
}
else
parse_primval ();
}
static void
parse_operand5 (void)
{
enum exp_opcode op;
switch (PEEK_TOKEN ())
{
case NOT:
op = UNOP_LOGICAL_NOT;
break;
case '-':
op = UNOP_NEG;
break;
default:
op = OP_NULL;
}
if (op != OP_NULL)
FORWARD_TOKEN ();
parse_operand6 ();
if (op != OP_NULL)
write_exp_elt_opcode (op);
}
static void
parse_operand4 (void)
{
enum exp_opcode op;
parse_operand5 ();
for (;;)
{
switch (PEEK_TOKEN ())
{
case '*':
op = BINOP_MUL;
break;
case '/':
op = BINOP_DIV;
break;
case MOD:
op = BINOP_MOD;
break;
case REM:
op = BINOP_REM;
break;
default:
return;
}
FORWARD_TOKEN ();
parse_operand5 ();
write_exp_elt_opcode (op);
}
}
static void
parse_operand3 (void)
{
enum exp_opcode op;
parse_operand4 ();
for (;;)
{
switch (PEEK_TOKEN ())
{
case '+':
op = BINOP_ADD;
break;
case '-':
op = BINOP_SUB;
break;
case SLASH_SLASH:
op = BINOP_CONCAT;
break;
default:
return;
}
FORWARD_TOKEN ();
parse_operand4 ();
write_exp_elt_opcode (op);
}
}
static void
parse_operand2 (void)
{
enum exp_opcode op;
parse_operand3 ();
for (;;)
{
if (check_token (IN))
{
parse_operand3 ();
write_exp_elt_opcode (BINOP_IN);
}
else
{
switch (PEEK_TOKEN ())
{
case '>':
op = BINOP_GTR;
break;
case GEQ:
op = BINOP_GEQ;
break;
case '<':
op = BINOP_LESS;
break;
case LEQ:
op = BINOP_LEQ;
break;
case '=':
op = BINOP_EQUAL;
break;
case NOTEQUAL:
op = BINOP_NOTEQUAL;
break;
default:
return;
}
FORWARD_TOKEN ();
parse_operand3 ();
write_exp_elt_opcode (op);
}
}
}
static void
parse_operand1 (void)
{
enum exp_opcode op;
parse_operand2 ();
for (;;)
{
switch (PEEK_TOKEN ())
{
case LOGAND:
op = BINOP_BITWISE_AND;
break;
case ANDIF:
op = BINOP_LOGICAL_AND;
break;
default:
return;
}
FORWARD_TOKEN ();
parse_operand2 ();
write_exp_elt_opcode (op);
}
}
static void
parse_operand0 (void)
{
enum exp_opcode op;
parse_operand1 ();
for (;;)
{
switch (PEEK_TOKEN ())
{
case LOGIOR:
op = BINOP_BITWISE_IOR;
break;
case LOGXOR:
op = BINOP_BITWISE_XOR;
break;
case ORIF:
op = BINOP_LOGICAL_OR;
break;
default:
return;
}
FORWARD_TOKEN ();
parse_operand1 ();
write_exp_elt_opcode (op);
}
}
static void
parse_expr (void)
{
parse_operand0 ();
if (check_token (GDB_ASSIGNMENT))
{
parse_expr ();
write_exp_elt_opcode (BINOP_ASSIGN);
}
}
static void
parse_then_alternative (void)
{
expect (THEN, "missing 'THEN' in 'IF' expression");
parse_expr ();
}
static void
parse_else_alternative (void)
{
if (check_token (ELSIF))
parse_if_expression_body ();
else if (check_token (ELSE))
parse_expr ();
else
error ("missing ELSE/ELSIF in IF expression");
}
static void
parse_if_expression_body (void)
{
parse_expr ();
parse_then_alternative ();
parse_else_alternative ();
write_exp_elt_opcode (TERNOP_COND);
}
static void
parse_if_expression (void)
{
require (IF);
parse_if_expression_body ();
expect (FI, "missing 'FI' at end of conditional expression");
}
static void
parse_untyped_expr (void)
{
switch (PEEK_TOKEN ())
{
case IF:
parse_if_expression ();
return;
case CASE:
error ("not implemented: CASE expression");
case '(':
switch (PEEK_TOKEN1 ())
{
case IF:
case CASE:
goto skip_lprn;
case '[':
skip_lprn:
FORWARD_TOKEN ();
parse_untyped_expr ();
expect (')', "missing ')'");
return;
default:;
}
default:
parse_operand0 ();
}
}
int
chill_parse (void)
{
terminal_buffer[0] = TOKEN_NOT_READ;
if (PEEK_TOKEN () == TYPENAME && PEEK_TOKEN1 () == END_TOKEN)
{
write_exp_elt_opcode (OP_TYPE);
write_exp_elt_type (PEEK_LVAL ().tsym.type);
write_exp_elt_opcode (OP_TYPE);
FORWARD_TOKEN ();
}
else
parse_expr ();
if (terminal_buffer[0] != END_TOKEN)
{
if (comma_terminates && terminal_buffer[0] == ',')
lexptr--;
else
error ("Junk after end of expression.");
}
return 0;
}
static char *tempbuf;
static int tempbufsize;
static int tempbufindex;
#define GROWBY_MIN_SIZE 64
#define CHECKBUF(size) \
do { \
if (tempbufindex + (size) >= tempbufsize) \
{ \
growbuf_by_size (size); \
} \
} while (0);
static void
growbuf_by_size (int count)
{
int growby;
growby = max (count, GROWBY_MIN_SIZE);
tempbufsize += growby;
if (tempbuf == NULL)
{
tempbuf = (char *) xmalloc (tempbufsize);
}
else
{
tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
}
}
static char *
match_simple_name_string (void)
{
char *tokptr = lexptr;
if (isalpha (*tokptr) || *tokptr == '_')
{
char *result;
do
{
tokptr++;
}
while (isalnum (*tokptr) || (*tokptr == '_'));
yylval.sval.ptr = lexptr;
yylval.sval.length = tokptr - lexptr;
lexptr = tokptr;
result = copy_name (yylval.sval);
return result;
}
return (NULL);
}
static int
decode_integer_value (int base, char **tokptrptr, LONGEST *ivalptr)
{
char *tokptr = *tokptrptr;
int temp;
int digits = 0;
while (*tokptr != '\0')
{
temp = *tokptr;
if (isupper (temp))
temp = tolower (temp);
tokptr++;
switch (temp)
{
case '_':
continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
temp -= '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
temp -= 'a';
temp += 10;
break;
default:
temp = base;
break;
}
if (temp < base)
{
digits++;
*ivalptr *= base;
*ivalptr += temp;
}
else
{
tokptr--;
break;
}
}
if (digits == 0)
{
return (0);
}
else
{
*tokptrptr = tokptr;
return (1);
}
}
static int
decode_integer_literal (LONGEST *valptr, char **tokptrptr)
{
char *tokptr = *tokptrptr;
int base = 0;
LONGEST ival = 0;
int explicit_base = 0;
switch (*tokptr)
{
case 'd':
case 'D':
explicit_base++;
base = 10;
tokptr++;
break;
case 'b':
case 'B':
explicit_base++;
base = 2;
tokptr++;
break;
case 'h':
case 'H':
explicit_base++;
base = 16;
tokptr++;
break;
case 'o':
case 'O':
explicit_base++;
base = 8;
tokptr++;
break;
default:
base = 10;
break;
}
if (explicit_base && (*tokptr++ != '\''))
{
return (0);
}
if (!decode_integer_value (base, &tokptr, &ival))
{
return (0);
}
else if (explicit_base && (*tokptr == '\''))
{
return (0);
}
else
{
*valptr = ival;
*tokptrptr = tokptr;
return (1);
}
}
static enum ch_terminal
match_float_literal (void)
{
char *tokptr = lexptr;
char *buf;
char *copy;
double dval;
extern double strtod ();
copy = buf = (char *) alloca (strlen (tokptr) + 1);
while (isdigit (*tokptr) || *tokptr == '_')
{
if (*tokptr != '_')
{
*copy++ = *tokptr;
}
tokptr++;
}
switch (*tokptr++)
{
case '.':
*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;
}
while (isdigit (*tokptr) || *tokptr == '_')
{
if (*tokptr != '_')
{
*copy++ = *tokptr;
}
tokptr++;
}
switch (*tokptr)
{
case 'e':
case 'E':
case 'd':
case 'D':
*copy++ = 'e';
tokptr++;
break;
default:
goto convert_float;
break;
}
collect_exponent:
if (*tokptr == '+' || *tokptr == '-')
{
*copy++ = *tokptr++;
}
while (isdigit (*tokptr))
{
*copy++ = *tokptr++;
}
convert_float:
*copy = '\0';
if (copy != buf)
{
dval = strtod (buf, ©);
if (*copy == '\0')
{
yylval.dval = dval;
lexptr = tokptr;
return (FLOAT_LITERAL);
}
}
return (0);
}
static enum ch_terminal
match_string_literal (void)
{
char *tokptr = lexptr;
int in_ctrlseq = 0;
LONGEST ival;
for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
{
CHECKBUF (1);
tryagain:;
if (in_ctrlseq)
{
while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
tokptr++;
if (*tokptr == ')')
{
in_ctrlseq = 0;
tokptr++;
goto tryagain;
}
else if (*tokptr != ',')
error ("Invalid control sequence");
tokptr++;
while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
tokptr++;
if (!decode_integer_literal (&ival, &tokptr))
error ("Invalid control sequence");
tokptr--;
}
else if (*tokptr == *lexptr)
{
if (*(tokptr + 1) == *lexptr)
{
ival = *tokptr++;
}
else
{
break;
}
}
else if (*tokptr == '^')
{
if (*(tokptr + 1) == '(')
{
in_ctrlseq = 1;
tokptr += 2;
if (!decode_integer_literal (&ival, &tokptr))
error ("Invalid control sequence");
tokptr--;
}
else if (*(tokptr + 1) == '^')
ival = *tokptr++;
else
error ("Invalid control sequence");
}
else
ival = *tokptr;
tempbuf[tempbufindex++] = ival;
}
if (in_ctrlseq)
error ("Invalid control sequence");
if (*tokptr == '\0'
|| (tempbufindex == 1 && *tokptr == '\''))
{
return (0);
}
else
{
tempbuf[tempbufindex] = '\0';
yylval.sval.ptr = tempbuf;
yylval.sval.length = tempbufindex;
lexptr = ++tokptr;
return (CHARACTER_STRING_LITERAL);
}
}
static enum ch_terminal
match_character_literal (void)
{
char *tokptr = lexptr;
LONGEST ival = 0;
if ((*tokptr == 'c' || *tokptr == 'C') && (*(tokptr + 1) == '\''))
{
tokptr += 2;
if (!decode_integer_value (16, &tokptr, &ival) || (*tokptr != '\''))
{
return (0);
}
tokptr++;
}
else if (*tokptr == '\'')
{
tokptr++;
if (*tokptr == '^')
{
if (*(tokptr + 1) == '(')
{
tokptr += 2;
if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
{
return (0);
}
}
else if (*(tokptr + 1) == '^')
{
ival = *tokptr;
tokptr += 2;
}
else
error ("Invalid control sequence");
}
else if (*tokptr == '\'')
{
ival = *tokptr;
tokptr += 2;
}
else
{
ival = *tokptr++;
}
if (*tokptr++ != '\'')
{
return (0);
}
}
else
{
return (0);
}
yylval.typed_val.val = ival;
yylval.typed_val.type = builtin_type_chill_char;
lexptr = tokptr;
return (CHARACTER_LITERAL);
}
static enum ch_terminal
match_integer_literal (void)
{
char *tokptr = lexptr;
LONGEST ival;
if (!decode_integer_literal (&ival, &tokptr))
{
return (0);
}
else
{
yylval.typed_val.val = ival;
#if defined(CC_HAS_LONG_LONG)
if (ival > (LONGEST) 2147483647U || ival < -(LONGEST) 2147483648U)
yylval.typed_val.type = builtin_type_long_long;
else
#endif
yylval.typed_val.type = builtin_type_int;
lexptr = tokptr;
return (INTEGER_LITERAL);
}
}
static enum ch_terminal
match_bitstring_literal (void)
{
register char *tokptr = lexptr;
int bitoffset = 0;
int bitcount = 0;
int bits_per_char;
int digit;
tempbufindex = 0;
CHECKBUF (1);
tempbuf[0] = 0;
switch (*tokptr++)
{
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;
}
if (*tokptr++ != '\'')
{
return (0);
}
while (*tokptr != '\0' && *tokptr != '\'')
{
digit = *tokptr;
if (isupper (digit))
digit = tolower (digit);
tokptr++;
switch (digit)
{
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 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
digit -= 'a';
digit += 10;
break;
default:
return 0;
}
if (digit >= 1 << bits_per_char)
{
error ("Too-large digit in bitstring or integer.");
}
else
{
int k = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? bits_per_char - 1 : 0;
for (; TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? k >= 0 : k < bits_per_char;
TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? k-- : k++)
{
bitcount++;
if (digit & (1 << k))
{
tempbuf[tempbufindex] |=
(TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
? (1 << (HOST_CHAR_BIT - 1 - bitoffset))
: (1 << bitoffset);
}
bitoffset++;
if (bitoffset == HOST_CHAR_BIT)
{
bitoffset = 0;
tempbufindex++;
CHECKBUF (1);
tempbuf[tempbufindex] = 0;
}
}
}
}
if (*tokptr++ != '\'')
{
return (0);
}
else
{
yylval.sval.ptr = tempbuf;
yylval.sval.length = bitcount;
lexptr = tokptr;
return (BIT_STRING_LITERAL);
}
}
struct token
{
char *operator;
int token;
};
static const struct token idtokentab[] =
{
{"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},
{">=", GEQ}
};
static enum ch_terminal
ch_lex (void)
{
unsigned int i;
enum ch_terminal token;
char *inputname;
struct symbol *sym;
while (isspace (*lexptr))
{
lexptr++;
}
switch (*lexptr)
{
case '\0':
return END_TOKEN;
case ',':
case '=':
case ';':
case '!':
case '+':
case '*':
case '(':
case ')':
case '[':
case ']':
return (*lexptr++);
}
switch (*lexptr)
{
case '\'':
case '\"':
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':
token = match_character_literal ();
if (token != 0)
{
return (token);
}
break;
case '$':
yylval.sval.ptr = lexptr;
do
{
lexptr++;
}
while (isalnum (*lexptr) || *lexptr == '_' || *lexptr == '$');
yylval.sval.length = lexptr - yylval.sval.ptr;
write_dollar_variable (yylval.sval);
return GDB_VARIABLE;
break;
}
for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
{
if (STREQN (lexptr, tokentab2[i].operator, 2))
{
lexptr += 2;
return (tokentab2[i].token);
}
}
switch (*lexptr)
{
case '-':
case ':':
case '/':
case '<':
case '>':
return (*lexptr++);
}
token = match_float_literal ();
if (token != 0)
{
return (token);
}
token = match_bitstring_literal ();
if (token != 0)
{
return (token);
}
token = match_integer_literal ();
if (token != 0)
{
return (token);
}
inputname = match_simple_name_string ();
if (inputname != NULL)
{
char *simplename = (char *) alloca (strlen (inputname) + 1);
char *dptr = simplename, *sptr = inputname;
for (; *sptr; sptr++)
*dptr++ = isupper (*sptr) ? tolower (*sptr) : *sptr;
*dptr = '\0';
for (i = 0; i < sizeof (idtokentab) / sizeof (idtokentab[0]); i++)
{
if (STREQ (simplename, idtokentab[i].operator))
{
return (idtokentab[i].token);
}
}
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;
yylval.ssym.stoken.length = 0;
yylval.ssym.sym = sym;
yylval.ssym.is_a_field_of_this = 0;
switch (SYMBOL_CLASS (sym))
{
case LOC_BLOCK:
return (GENERAL_PROCEDURE_NAME);
case LOC_STATIC:
return (LOCATION_NAME);
case LOC_REGISTER:
case LOC_ARG:
case LOC_REF_ARG:
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL:
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_OPTIMIZED_OUT:
error ("Symbol \"%s\" names no location.", inputname);
break;
default:
internal_error (__FILE__, __LINE__,
"unhandled SYMBOL_CLASS in ch_lex()");
break;
}
}
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.", inputname);
}
}
switch (*lexptr)
{
case '.':
lexptr++;
while (isspace (*lexptr))
lexptr++;
inputname = match_simple_name_string ();
if (!inputname)
return '.';
return DOT_FIELD_NAME;
}
return (ILLEGAL_TOKEN);
}
static void
write_lower_upper_value (enum exp_opcode opcode,
struct type *type)
{
if (type == NULL)
write_exp_elt_opcode (opcode);
else
{
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
chill_error (char *msg)
{
}