X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/d1f5c8043acfeb2b8e2ecdfca6dc43af016719cc..380c32d50df2dba5393429b52effd51b1a3c0f0f:/gdb/ch-exp.c diff --git a/gdb/ch-exp.c b/gdb/ch-exp.c index 492f3765a7..cc7d7f7514 100644 --- a/gdb/ch-exp.c +++ b/gdb/ch-exp.c @@ -26,15 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ during the process of parsing; the lower levels of the tree always come first in the result. - Note that malloc's and realloc's in this file are transformed to - xmalloc and xrealloc respectively by the same sed command in the - makefile that remaps any other malloc/realloc inserted by the parser - generator. Doing this with #defines and trying to control the interaction - with include files ( and for example) just became - too messy, particularly when such includes can be inserted at random - times by the parser generator. - - Also note that the language accepted by this parser is more liberal + Note that the language accepted by this parser is more liberal than the one accepted by an actual Chill compiler. For example, the language rule that a simple name string can not be one of the reserved simple name strings is not enforced (e.g "case" is not treated as a @@ -52,7 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ */ #include "defs.h" -#include +#include "gdb_string.h" #include #include "expression.h" #include "language.h" @@ -63,11 +55,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "symfile.h" /* Required by objfiles.h. */ #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ +#ifdef __GNUC__ +#define INLINE __inline__ +#endif + typedef union { LONGEST lval; - unsigned LONGEST ulval; + ULONGEST ulval; struct { LONGEST val; struct type *type; @@ -83,6 +79,7 @@ typedef union enum ch_terminal { END_TOKEN = 0, /* '\001' ... '\xff' come first. */ + OPEN_PAREN = '(', TOKEN_NOT_READ = 999, INTEGER_LITERAL, BOOLEAN_LITERAL, @@ -138,13 +135,55 @@ enum ch_terminal { }; /* Forward declarations. */ -static void parse_expr (); -static void parse_primval (); -static void parse_untyped_expr (); -static int parse_opt_untyped_expr (); -static void parse_if_expression_body PARAMS((void)); + static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *)); -static enum ch_terminal ch_lex (); +static enum ch_terminal match_bitstring_literal PARAMS ((void)); +static enum ch_terminal match_integer_literal PARAMS ((void)); +static enum ch_terminal match_character_literal PARAMS ((void)); +static enum ch_terminal match_string_literal PARAMS ((void)); +static enum ch_terminal match_float_literal PARAMS ((void)); +static enum ch_terminal match_float_literal PARAMS ((void)); +static int decode_integer_literal PARAMS ((LONGEST *, char **)); +static int decode_integer_value PARAMS ((int, char **, LONGEST *)); +static char *match_simple_name_string PARAMS ((void)); +static void growbuf_by_size PARAMS ((int)); +static void parse_untyped_expr PARAMS ((void)); +static void parse_if_expression PARAMS ((void)); +static void parse_else_alternative PARAMS ((void)); +static void parse_then_alternative PARAMS ((void)); +static void parse_expr PARAMS ((void)); +static void parse_operand0 PARAMS ((void)); +static void parse_operand1 PARAMS ((void)); +static void parse_operand2 PARAMS ((void)); +static void parse_operand3 PARAMS ((void)); +static void parse_operand4 PARAMS ((void)); +static void parse_operand5 PARAMS ((void)); +static void parse_operand6 PARAMS ((void)); +static void parse_primval PARAMS ((void)); +static void parse_tuple PARAMS ((struct type *)); +static void parse_opt_element_list PARAMS ((struct type *)); +static void parse_tuple_element PARAMS ((struct type *)); +static void parse_named_record_element PARAMS ((void)); +static void parse_call PARAMS ((void)); +static struct type *parse_mode_or_normal_call PARAMS ((void)); +#if 0 +static struct type *parse_mode_call PARAMS ((void)); +#endif +static void parse_unary_call PARAMS ((void)); +static int parse_opt_untyped_expr PARAMS ((void)); +static void parse_case_label PARAMS ((void)); +static int expect PARAMS ((enum ch_terminal, char *)); +static void parse_expr PARAMS ((void)); +static void parse_primval PARAMS ((void)); +static void parse_untyped_expr PARAMS ((void)); +static int parse_opt_untyped_expr PARAMS ((void)); +static void parse_if_expression_body PARAMS((void)); +static enum ch_terminal ch_lex PARAMS ((void)); +INLINE static enum ch_terminal PEEK_TOKEN PARAMS ((void)); +static enum ch_terminal peek_token_ PARAMS ((int)); +static void forward_token_ PARAMS ((void)); +static void require PARAMS ((enum ch_terminal)); +static int check_token PARAMS ((enum ch_terminal)); #define MAX_LOOK_AHEAD 2 static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD+1] = { @@ -154,10 +193,7 @@ static YYSTYPE val_buffer[MAX_LOOK_AHEAD+1]; /*int current_token, lookahead_token;*/ -#ifdef __GNUC__ -__inline__ -#endif -static enum ch_terminal +INLINE static enum ch_terminal PEEK_TOKEN() { if (terminal_buffer[0] == TOKEN_NOT_READ) @@ -184,6 +220,8 @@ peek_token_ (i) return terminal_buffer[i]; } +#if 0 + static void pushback_token (code, node) enum ch_terminal code; @@ -201,6 +239,8 @@ pushback_token (code, node) val_buffer[0] = node; } +#endif + static void forward_token_() { @@ -217,7 +257,7 @@ forward_token_() /* Skip the next token. if it isn't TOKEN, the parser is broken. */ -void +static void require(token) enum ch_terminal token; { @@ -230,7 +270,7 @@ require(token) FORWARD_TOKEN(); } -int +static int check_token (token) enum ch_terminal token; { @@ -243,8 +283,8 @@ check_token (token) /* return 0 if expected token was not found, else return 1. */ -int -expect(token, message) +static int +expect (token, message) enum ch_terminal token; char *message; { @@ -411,7 +451,9 @@ parse_unary_call () /* Parse NAME '(' MODENAME ')'. */ -struct type * +#if 0 + +static struct type * parse_mode_call () { struct type *type; @@ -425,7 +467,9 @@ parse_mode_call () return type; } -struct type * +#endif + +static struct type * parse_mode_or_normal_call () { struct type *type; @@ -489,9 +533,11 @@ static void parse_named_record_element () { struct stoken label; + char buf[256]; label = PEEK_LVAL ().sval; - expect (FIELD_NAME, "expected a field name here `%s'", lexptr); + sprintf (buf, "expected a field name here `%s'", lexptr); + expect (FIELD_NAME, buf); if (check_token (',')) parse_named_record_element (); else if (check_token (':')) @@ -503,10 +549,11 @@ parse_named_record_element () write_exp_elt_opcode (OP_LABELED); } -/* Returns one or nore TREE_LIST nodes, in reverse order. */ +/* Returns one or more TREE_LIST nodes, in reverse order. */ static void -parse_tuple_element () +parse_tuple_element (type) + struct type *type; { if (PEEK_TOKEN () == FIELD_NAME) { @@ -520,7 +567,32 @@ parse_tuple_element () if (check_token ('*')) { expect (')', "missing ')' after '*' case label list"); - error ("(*) not implemented in case label list"); + if (type) + { + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + /* do this as a range from low to high */ + 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 (*)"); + /* lower bound */ + write_exp_elt_opcode (OP_LONG); + write_exp_elt_type (range_type); + write_exp_elt_longcst (low_bound); + write_exp_elt_opcode (OP_LONG); + /* upper bound */ + 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 { @@ -546,14 +618,15 @@ parse_tuple_element () /* Matches: a COMMA-separated list of tuple elements. Returns a list (of TREE_LIST nodes). */ static void -parse_opt_element_list () +parse_opt_element_list (type) + struct type *type; { arglist_len = 0; if (PEEK_TOKEN () == ']') return; for (;;) { - parse_tuple_element (); + parse_tuple_element (type); arglist_len++; if (PEEK_TOKEN () == ']') break; @@ -569,16 +642,25 @@ static void parse_tuple (mode) struct type *mode; { + struct type *type; + if (mode) + type = check_typedef (mode); + else + type = 0; require ('['); start_arglist (); - parse_opt_element_list (); + 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 (mode) + 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); @@ -686,12 +768,21 @@ parse_primval () 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; - case CARD: op_name = "CARD"; goto unimplemented_unary_builtin; - case MAX_TOKEN: op_name = "MAX"; goto unimplemented_unary_builtin; - case MIN_TOKEN: op_name = "MIN"; goto unimplemented_unary_builtin; unimplemented_unary_builtin: parse_unary_call (); error ("not implemented: %s builtin function", op_name); @@ -772,7 +863,7 @@ parse_primval () } write_exp_elt_opcode (UNOP_IND); continue; - case '(': + case OPEN_PAREN: parse_call (); continue; case CHARACTER_STRING_LITERAL: @@ -784,6 +875,55 @@ parse_primval () 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; } @@ -1089,11 +1229,11 @@ growbuf_by_size (count) tempbufsize += growby; if (tempbuf == NULL) { - tempbuf = (char *) malloc (tempbufsize); + tempbuf = (char *) xmalloc (tempbufsize); } else { - tempbuf = (char *) realloc (tempbuf, tempbufsize); + tempbuf = (char *) xrealloc (tempbuf, tempbufsize); } } @@ -1407,23 +1547,67 @@ static enum ch_terminal match_string_literal () { char *tokptr = lexptr; + int in_ctrlseq = 0; + LONGEST ival; for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++) { CHECKBUF (1); - if (*tokptr == *lexptr) + tryagain: ; + if (in_ctrlseq) { - if (*(tokptr + 1) == *lexptr) + /* skip possible whitespaces */ + while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr) + tokptr++; + if (*tokptr == ')') { + in_ctrlseq = 0; tokptr++; + goto tryagain; + } + else if (*tokptr != ',') + error ("Invalid control sequence"); + tokptr++; + /* skip possible whitespaces */ + 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; } } - tempbuf[tempbufindex++] = *tokptr; + 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' /* no terminator */ || (tempbufindex == 1 && *tokptr == '\'')) /* char literal */ { @@ -1452,12 +1636,6 @@ match_string_literal () 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. */ @@ -1486,28 +1664,39 @@ match_character_literal () /* Determine which form we have, either a control sequence or the single character form. */ - if ((*tokptr == '^') && (*(tokptr + 1) == '(')) + if (*tokptr == '^') { -#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 ')'. - FIXME: We currently don't handle the multiple integer literal - form. */ - tokptr += 2; - if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')')) + if (*(tokptr + 1) == '(') { - return (0); + /* 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 ')'. */ + tokptr += 2; + if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')')) + { + return (0); + } } -#else - return (0); -#endif + else if (*(tokptr + 1) == '^') + { + ival = *tokptr; + tokptr += 2; + } + else + /* fail */ + error ("Invalid control sequence"); + } + else if (*tokptr == '\'') + { + /* this must be duplicated */ + ival = *tokptr; + tokptr += 2; } else { ival = *tokptr++; } - + /* The trailing quote has not yet been consumed. If we don't find it, then we have no match. */ @@ -1621,7 +1810,8 @@ match_bitstring_literal () digit += 10; break; default: - error ("Invalid character in bitstring or integer."); + /* this is not a bitstring literal, probably an integer */ + return 0; } if (digit >= 1 << bits_per_char) { @@ -1921,6 +2111,9 @@ ch_lex () case LOC_OPTIMIZED_OUT: error ("Symbol \"%s\" names no location.", inputname); break; + case LOC_UNRESOLVED: + error ("unhandled SYMBOL_CLASS in ch_lex()"); + break; } } else if (!have_full_symbols () && !have_partial_symbols ()) @@ -1959,7 +2152,6 @@ write_lower_upper_value (opcode, type) write_exp_elt_opcode (opcode); else { - extern LONGEST type_lower_upper (); struct type *result_type; LONGEST val = type_lower_upper (opcode, type, &result_type); write_exp_elt_opcode (OP_LONG);