diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /gdb/ch-exp.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'gdb/ch-exp.c')
-rw-r--r-- | gdb/ch-exp.c | 2169 |
1 files changed, 0 insertions, 2169 deletions
diff --git a/gdb/ch-exp.c b/gdb/ch-exp.c deleted file mode 100644 index 45436a3..0000000 --- a/gdb/ch-exp.c +++ /dev/null @@ -1,2169 +0,0 @@ -/* Parser for GNU CHILL (CCITT High-Level Language) -*- C -*- - Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Parse a Chill expression from text in a string, - and return the result as a struct expression pointer. - That structure contains arithmetic operations in reverse polish, - with constants represented by operations that are followed by special data. - See expression.h for the details of the format. - What is important here is that it can be built up sequentially - during the process of parsing; the lower levels of the tree always - come first in the result. - - Note that 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 - reserved name). Another example is that Chill is a strongly typed - language, and certain expressions that violate the type constraints - may still be evaluated if gdb can do so in a meaningful manner, while - such expressions would be rejected by the compiler. The reason for - this more liberal behavior is the philosophy that the debugger - is intended to be a tool that is used by the programmer when things - go wrong, and as such, it should provide as few artificial barriers - to it's use as possible. If it can do something meaningful, even - something that violates language contraints that are enforced by the - compiler, it should do so without complaint. - - */ - -#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" /* Required by objfiles.h. */ -#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; - 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, - /* '\001' ... '\xff' come first. */ - 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, /* '.' followed by <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 -}; - -/* Forward declarations. */ - -static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *)); -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] = { - TOKEN_NOT_READ, TOKEN_NOT_READ, TOKEN_NOT_READ}; -static YYSTYPE yylval; -static YYSTYPE val_buffer[MAX_LOOK_AHEAD+1]; - -/*int current_token, lookahead_token;*/ - -INLINE static enum ch_terminal -PEEK_TOKEN() -{ - 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_ (i) - int i; -{ - if (i > MAX_LOOK_AHEAD) - fatal ("internal error - 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 (code, node) - enum ch_terminal code; - YYSTYPE node; -{ - int i; - if (terminal_buffer[MAX_LOOK_AHEAD] != TOKEN_NOT_READ) - fatal ("internal error - 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_() -{ - 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_() - -/* Skip the next token. - if it isn't TOKEN, the parser is broken. */ - -static void -require(token) - enum ch_terminal token; -{ - if (PEEK_TOKEN() != token) - { - char buf[80]; - sprintf (buf, "internal parser error - expected token %d", (int)token); - fatal(buf); - } - FORWARD_TOKEN(); -} - -static int -check_token (token) - enum ch_terminal token; -{ - if (PEEK_TOKEN() != token) - return 0; - FORWARD_TOKEN (); - return 1; -} - -/* return 0 if expected token was not found, - else return 1. -*/ -static int -expect (token, message) - 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 (allow_all) - int allow_all; /* 1 if ALL is allowed as a postfix */ -{ - 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 () -{ - 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 () -{ - tree name = parse_opt_name_string (0); - if (name) - return name; - if (pass == 1) - error ("expected a name string here"); - return error_mark_node; -} - -/* Matches: <name_string> - Returns if pass 1: the identifier. - Returns if pass 2: a decl or value for identifier. */ - -static tree -parse_name () -{ - 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 (expr) - tree expr; -{ - if (pass == 1 && !ignoring) - expr = build1 (PAREN_EXPR, NULL_TREE, expr); - pushback_token (EXPR, expr); -} -#endif - -/* Matches: <case label> */ - -static void -parse_case_label () -{ - if (check_token (ELSE)) - error ("ELSE in tuples labels not implemented"); - /* Does not handle the case of a mode name. FIXME */ - parse_expr (); - if (check_token (':')) - { - parse_expr (); - write_exp_elt_opcode (BINOP_RANGE); - } -} - -static int -parse_opt_untyped_expr () -{ - switch (PEEK_TOKEN ()) - { - case ',': - case ':': - case ')': - return 0; - default: - parse_untyped_expr (); - return 1; - } -} - -static void -parse_unary_call () -{ - FORWARD_TOKEN (); - expect ('(', NULL); - parse_expr (); - expect (')', NULL); -} - -/* Parse NAME '(' MODENAME ')'. */ - -#if 0 - -static struct type * -parse_mode_call () -{ - 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 () -{ - 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; -} - -/* Parse something that looks like a function call. - Assume we have parsed the function, and are at the '('. */ - -static void -parse_call () -{ - int arg_count; - require ('('); - /* This is to save the value of arglist_len - being accumulated for each dimension. */ - 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 () -{ - 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); -} - -/* Returns one or more TREE_LIST nodes, in reverse order. */ - -static void -parse_tuple_element (type) - struct type *type; -{ - if (PEEK_TOKEN () == DOT_FIELD_NAME) - { - /* Parse a labelled structure tuple. */ - 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) - { - /* 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 - { - parse_case_label (); - while (check_token (',')) - { - parse_case_label (); - write_exp_elt_opcode (BINOP_COMMA); - } - expect (')', NULL); - } - } - else - parse_untyped_expr (); - if (check_token (':')) - { - /* A powerset range or a labeled Array. */ - parse_untyped_expr (); - write_exp_elt_opcode (BINOP_RANGE); - } -} - -/* Matches: a COMMA-separated list of tuple elements. - Returns a list (of TREE_LIST nodes). */ -static void -parse_opt_element_list (type) - 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"); - } -} - -/* Parses: '[' elements ']' - If modename is non-NULL it prefixed the tuple. */ - -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 (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 () -{ - 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 (); - /* This is pseudo-Chill, similar to C's '(TYPE[])EXPR' - which casts to an artificial array. */ - 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: /* gdb specific */ - 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: - /* Handle string repetition. (See comment in parse_operand5.) */ - 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 () -{ - 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() -{ - enum exp_opcode op; - /* We are supposed to be looking for a <string repetition operator>, - but in general we can't distinguish that from a parenthesized - expression. This is especially difficult if we allow the - string operand to be a constant expression (as requested by - some users), and not just a string literal. - Consider: LPRN expr RPRN LPRN expr RPRN - Is that a function call or string repetition? - Instead, we handle string repetition in parse_primval, - and build_generalized_call. */ - 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 () -{ - 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 () -{ - 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 () -{ - 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 () -{ - 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 () -{ - 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 () -{ - parse_operand0 (); - if (check_token (GDB_ASSIGNMENT)) - { - parse_expr (); - write_exp_elt_opcode (BINOP_ASSIGN); - } -} - -static void -parse_then_alternative () -{ - expect (THEN, "missing 'THEN' in 'IF' expression"); - parse_expr (); -} - -static void -parse_else_alternative () -{ - if (check_token (ELSIF)) - parse_if_expression_body (); - else if (check_token (ELSE)) - parse_expr (); - else - error ("missing ELSE/ELSIF in IF expression"); -} - -/* Matches: <boolean expression> <then alternative> <else alternative> */ - -static void -parse_if_expression_body () -{ - parse_expr (); - parse_then_alternative (); - parse_else_alternative (); - write_exp_elt_opcode (TERNOP_COND); -} - -static void -parse_if_expression () -{ - require (IF); - parse_if_expression_body (); - expect (FI, "missing 'FI' at end of conditional expression"); -} - -/* An <untyped_expr> is a superset of <expr>. It also includes - <conditional expressions> and untyped <tuples>, whose types - are not given by their constituents. Hence, these are only - allowed in certain contexts that expect a certain type. - You should call convert() to fix up the <untyped_expr>. */ - -static void -parse_untyped_expr () -{ - 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: ; - /* fall through */ - } - default: - parse_operand0 (); - } -} - -int -chill_parse () -{ - 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--; /* Put the comma back. */ - else - error ("Junk after end of expression."); - } - return 0; -} - - -/* 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 *) xmalloc (tempbufsize); - } - else - { - tempbuf = (char *) xrealloc (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. */ - -static char * -match_simple_name_string () -{ - 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); -} - -/* Start looking for a value composed of valid digits as set by the base - in use. Note that '_' characters are valid anywhere, in any quantity, - and are simply ignored. Since we must find at least one valid digit, - or reject this token as an integer literal, we keep track of how many - digits we have encountered. */ - -static int -decode_integer_value (base, tokptrptr, ivalptr) - 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 - { - /* Found something not in domain for current base. */ - tokptr--; /* Unconsume what gave us indigestion. */ - break; - } - } - - /* If we didn't find any digits, then we don't have a valid integer - value, so reject the entire token. Otherwise, update the lexical - scan pointer, and return non-zero for success. */ - - if (digits == 0) - { - return (0); - } - else - { - *tokptrptr = tokptr; - return (1); - } -} - -static int -decode_integer_literal (valptr, tokptrptr) - LONGEST *valptr; - char **tokptrptr; -{ - char *tokptr = *tokptrptr; - int base = 0; - LONGEST ival = 0; - int explicit_base = 0; - - /* Look for an explicit base specifier, which is optional. */ - - 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 we found an explicit base ensure that the character after the - explicit base is a single quote. */ - - if (explicit_base && (*tokptr++ != '\'')) - { - return (0); - } - - /* Attempt to decode whatever follows as an integer value in the - indicated base, updating the token pointer in the process and - computing the value into ival. Also, if we have an explicit - base, then the next character must not be a single quote, or we - have a bitstring literal, so reject the entire token in this case. - Otherwise, update the lexical scan pointer, and return non-zero - for success. */ - - if (!decode_integer_value (base, &tokptr, &ival)) - { - return (0); - } - else if (explicit_base && (*tokptr == '\'')) - { - return (0); - } - else - { - *valptr = ival; - *tokptrptr = tokptr; - return (1); - } -} - -/* 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 enum ch_terminal -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 enum ch_terminal -match_string_literal () -{ - char *tokptr = lexptr; - int in_ctrlseq = 0; - LONGEST ival; - - for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++) - { - CHECKBUF (1); - tryagain: ; - if (in_ctrlseq) - { - /* 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; - } - } - 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 */ - { - 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 - in parenthesis and introduced with a circumflex character. - - EX: 'a' '^(7)' '^(7,8)' - - 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. - - Returns CHARACTER_LITERAL if a match is found. - */ - -static enum ch_terminal -match_character_literal () -{ - char *tokptr = lexptr; - LONGEST ival = 0; - - 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 - single quote character. */ - tokptr += 2; - if (!decode_integer_value (16, &tokptr, &ival) || (*tokptr != '\'')) - { - return (0); - } - tokptr++; - } - else if (*tokptr == '\'') - { - tokptr++; - - /* Determine which form we have, either a control sequence or the - single character form. */ - - if (*tokptr == '^') - { - if (*(tokptr + 1) == '(') - { - /* 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 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. */ - - if (*tokptr++ != '\'') - { - return (0); - } - } - else - { - /* Not a character literal. */ - return (0); - } - yylval.typed_val.val = ival; - yylval.typed_val.type = builtin_type_chill_char; - lexptr = tokptr; - return (CHARACTER_LITERAL); -} - -/* Recognize an integer literal, as specified in Z.200 sec 5.2.4.2. - Note that according to 5.2.4.2, a single "_" is also a valid integer - literal, however GNU-chill requires there to be at least one "digit" - in any integer literal. */ - -static enum ch_terminal -match_integer_literal () -{ - 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) && defined(__STDC__) - 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); - } -} - -/* 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 enum ch_terminal -match_bitstring_literal () -{ - 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++) - { - 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 '_': - 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: - /* this is not a bitstring literal, probably an integer */ - return 0; - } - if (digit >= 1 << bits_per_char) - { - /* Found something not in domain for current base. */ - error ("Too-large digit in bitstring or integer."); - } - 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; - } - } - } - } - - /* Verify that we consumed everything up to the trailing single quote, - and that we found some bits (IE not just underbars). */ - - 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 } -}; - -/* Read one token, getting characters through lexptr. */ -/* This is where we will check to make sure that the language and the - operators used are compatible. */ - -static enum ch_terminal -ch_lex () -{ - unsigned int i; - enum ch_terminal token; - char *inputname; - struct symbol *sym; - - /* Skip over any leading whitespace. */ - while (isspace (*lexptr)) - { - lexptr++; - } - /* Look for special single character cases which can't be the first - character of some other multicharacter token. */ - switch (*lexptr) - { - case '\0': - return END_TOKEN; - 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, 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': - 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; - } - /* See if it is a special token of length 2. */ - for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++) - { - if (STREQN (lexptr, tokentab2[i].operator, 2)) - { - lexptr += 2; - return (tokentab2[i].token); - } - } - /* Look for single character cases which which could be the first - character of some other multicharacter token, but aren't, or we - would already have found it. */ - switch (*lexptr) - { - case '-': - case ':': - case '/': - case '<': - case '>': - return (*lexptr++); - } - /* 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) - { - return (token); - } - token = match_bitstring_literal (); - if (token != 0) - { - return (token); - } - token = match_integer_literal (); - if (token != 0) - { - return (token); - } - - /* Try to match a simple name string, and if a match is found, then - further classify what sort of name it is and return an appropriate - token. Note that attempting to match a simple name string consumes - 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. */ - - 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'; - - /* 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; - yylval.ssym.stoken.length = 0; - yylval.ssym.sym = sym; - yylval.ssym.is_a_field_of_this = 0; /* FIXME, C++'ism */ - switch (SYMBOL_CLASS (sym)) - { - case LOC_BLOCK: - /* Found a procedure name. */ - return (GENERAL_PROCEDURE_NAME); - case LOC_STATIC: - /* Found a global or local static variable. */ - 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; - case LOC_UNRESOLVED: - error ("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); - } - } - - /* 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 DOT_FIELD_NAME; - } - - return (ILLEGAL_TOKEN); -} - -static void -write_lower_upper_value (opcode, type) - enum exp_opcode opcode; /* Either UNOP_LOWER or UNOP_UPPER */ - 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 (msg) - char *msg; -{ - /* Never used. */ -} |