diff options
Diffstat (limited to 'gdb/ch-exp.y')
-rw-r--r-- | gdb/ch-exp.y | 196 |
1 files changed, 187 insertions, 9 deletions
diff --git a/gdb/ch-exp.y b/gdb/ch-exp.y index 141463d..2f6376a3 100644 --- a/gdb/ch-exp.y +++ b/gdb/ch-exp.y @@ -90,6 +90,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define yy_yyv chill_yyv #define yyval chill_val #define yylloc chill_lloc +#define yyreds chill_reds /* With YYDEBUG defined */ +#define yytoks chill_toks /* With YYDEBUG defined */ #define yyss chill_yyss /* byacc */ #define yyssp chill_yysp /* byacc */ #define yyvs chill_yyvs /* byacc */ @@ -104,7 +106,9 @@ yyerror PARAMS ((char *)); int yyparse PARAMS ((void)); -/* #define YYDEBUG 1 */ +#if MAINTENANCE_CMDS +#define YYDEBUG 1 +#endif %} @@ -190,6 +194,15 @@ yyparse PARAMS ((void)); %token <voidval> ELSIF %token <voidval> ILLEGAL_TOKEN +/* Tokens which are not Chill tokens used in expressions, but rather GDB + specific things that we recognize in the same context as Chill tokens + (register names for example). */ + +%token <lval> GDB_REGNAME /* Machine register name */ +%token <lval> GDB_LAST /* Value history */ +%token <ivar> GDB_VARIABLE /* Convenience variable */ +%token <voidval> GDB_ASSIGNMENT /* Assign value to somewhere */ + %type <voidval> location %type <voidval> access_name %type <voidval> primitive_value @@ -247,6 +260,8 @@ yyparse PARAMS ((void)); %type <voidval> case_label_specification %type <voidval> buffer_location +%type <voidval> single_assignment_action + %% /* Z.200, 5.3.1 */ @@ -287,6 +302,24 @@ access_name : LOCATION_NAME write_exp_elt_sym ($1.sym); write_exp_elt_opcode (OP_VAR_VALUE); } + | GDB_LAST /* gdb specific */ + { + write_exp_elt_opcode (OP_LAST); + write_exp_elt_longcst ($1); + write_exp_elt_opcode (OP_LAST); + } + | GDB_REGNAME /* gdb specific */ + { + write_exp_elt_opcode (OP_REGISTER); + write_exp_elt_longcst ($1); + write_exp_elt_opcode (OP_REGISTER); + } + | GDB_VARIABLE /* gdb specific */ + { + write_exp_elt_opcode (OP_INTERNALVAR); + write_exp_elt_intern ($1); + write_exp_elt_opcode (OP_INTERNALVAR); + } | FIXME { $$ = 0; /* FIXME */ @@ -604,6 +637,10 @@ operand_0 : operand_1 { write_exp_elt_opcode (BINOP_BITWISE_XOR); } + | single_assignment_action + { + $$ = 0; /* FIXME */ + } ; /* Z.200, 5.3.4 */ @@ -740,6 +777,13 @@ operand_6 : POINTER location ; +/* Z.200, 6.2 */ + +single_assignment_action : location GDB_ASSIGNMENT value + { + write_exp_elt_opcode (BINOP_ASSIGN); + } + /* Z.200, 12.4.3 */ /* FIXME: For now we just accept only a single integer literal. */ @@ -1036,6 +1080,131 @@ match_integer_literal () } } +/* Recognize tokens that start with '$'. These include: + + $regname A native register name or a "standard + register name". + Return token GDB_REGNAME. + + $variable A convenience variable with a name chosen + by the user. + Return token GDB_VARIABLE. + + $digits Value history with index <digits>, starting + from the first value which has index 1. + Return GDB_LAST. + + $$digits Value history with index <digits> relative + to the last value. I.E. $$0 is the last + value, $$1 is the one previous to that, $$2 + is the one previous to $$1, etc. + Return token GDB_LAST. + + $ | $0 | $$0 The last value in the value history. + Return token GDB_LAST. + + $$ An abbreviation for the second to the last + value in the value history, I.E. $$1 + Return token GDB_LAST. + + Note that we currently assume that register names and convenience + variables follow the convention of starting with a letter or '_'. + + */ + +static int +match_dollar_tokens () +{ + char *tokptr; + int regno; + int namelength; + int negate; + int ival; + + /* We will always have a successful match, even if it is just for + a single '$', the abbreviation for $$0. So advance lexptr. */ + + tokptr = ++lexptr; + + if (*tokptr == '_' || isalpha (*tokptr)) + { + /* Look for a match with a native register name, usually something + like "r0" for example. */ + + for (regno = 0; regno < NUM_REGS; regno++) + { + namelength = strlen (reg_names[regno]); + if (STREQN (tokptr, reg_names[regno], namelength) + && !isalnum (tokptr[namelength])) + { + yylval.lval = regno; + lexptr += namelength + 1; + return (GDB_REGNAME); + } + } + + /* Look for a match with a standard register name, usually something + like "pc", which gdb always recognizes as the program counter + regardless of what the native register name is. */ + + for (regno = 0; regno < num_std_regs; regno++) + { + namelength = strlen (std_regs[regno].name); + if (STREQN (tokptr, std_regs[regno].name, namelength) + && !isalnum (tokptr[namelength])) + { + yylval.lval = std_regs[regno].regnum; + lexptr += namelength; + return (GDB_REGNAME); + } + } + + /* Attempt to match against a convenience variable. Note that + this will always succeed, because if no variable of that name + already exists, the lookup_internalvar will create one for us. + Also note that both lexptr and tokptr currently point to the + start of the input string we are trying to match, and that we + have already tested the first character for non-numeric, so we + don't have to treat it specially. */ + + while (*tokptr == '_' || isalnum (*tokptr)) + { + tokptr++; + } + yylval.sval.ptr = lexptr; + yylval.sval.length = tokptr - lexptr; + yylval.ivar = lookup_internalvar (copy_name (yylval.sval)); + lexptr = tokptr; + return (GDB_VARIABLE); + } + + /* Since we didn't match against a register name or convenience + variable, our only choice left is a history value. */ + + if (*tokptr == '$') + { + negate = 1; + ival = 1; + tokptr++; + } + else + { + negate = 0; + ival = 0; + } + + /* Attempt to decode more characters as an integer value giving + the index in the history list. If successful, the value will + overwrite ival (currently 0 or 1), and if not, ival will be + left alone, which is good since it is currently correct for + the '$' or '$$' case. */ + + decode_integer_literal (&ival, &tokptr); + yylval.lval = negate ? -ival : ival; + lexptr = tokptr; + return (GDB_LAST); +} + #if 0 static void convert_float () { @@ -1103,6 +1272,7 @@ static const struct token tokentab3[] = static const struct token tokentab2[] = { + { ":=", GDB_ASSIGNMENT }, { "//", SLASH_SLASH }, { "/=", NOTEQUAL }, { "<=", LEQ }, @@ -1136,7 +1306,6 @@ yylex () return (0); case '.': case '=': - case ':': case ';': case '!': case '+': @@ -1150,7 +1319,8 @@ yylex () return (*lexptr++); } /* Look for characters which start a particular kind of multicharacter - token, such as a character literal. */ + token, such as a character literal, register name, convenience + variable name, etc. */ switch (*lexptr) { case 'C': @@ -1162,11 +1332,18 @@ yylex () return (token); } break; + case '$': + token = match_dollar_tokens (); + if (token != 0) + { + return (token); + } + break; } /* See if it is a special token of length 5. */ for (i = 0; i < sizeof (tokentab5) / sizeof (tokentab5[0]); i++) { - if (strncmp (lexptr, tokentab5[i].operator, 5) == 0) + if (STREQN (lexptr, tokentab5[i].operator, 5)) { lexptr += 5; return (tokentab5[i].token); @@ -1175,7 +1352,7 @@ yylex () /* See if it is a special token of length 4. */ for (i = 0; i < sizeof (tokentab4) / sizeof (tokentab4[0]); i++) { - if (strncmp (lexptr, tokentab4[i].operator, 4) == 0) + if (STREQN (lexptr, tokentab4[i].operator, 4)) { lexptr += 4; return (tokentab4[i].token); @@ -1184,7 +1361,7 @@ yylex () /* See if it is a special token of length 3. */ for (i = 0; i < sizeof (tokentab3) / sizeof (tokentab3[0]); i++) { - if (strncmp (lexptr, tokentab3[i].operator, 3) == 0) + if (STREQN (lexptr, tokentab3[i].operator, 3)) { lexptr += 3; return (tokentab3[i].token); @@ -1193,7 +1370,7 @@ yylex () /* See if it is a special token of length 2. */ for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++) { - if (strncmp (lexptr, tokentab2[i].operator, 2) == 0) + if (STREQN (lexptr, tokentab2[i].operator, 2)) { lexptr += 2; return (tokentab2[i].token); @@ -1204,19 +1381,20 @@ yylex () would already have found it. */ switch (*lexptr) { + case ':': case '/': case '<': case '>': return (*lexptr++); } /* Look for other special tokens. */ - if (strncmp (lexptr, "TRUE", 4) == 0) /* FIXME: What about lowercase? */ + if (STREQN (lexptr, "TRUE", 4)) /* FIXME: What about lowercase? */ { yylval.ulval = 1; lexptr += 4; return (BOOLEAN_LITERAL); } - if (strncmp (lexptr, "FALSE", 5) == 0) /* FIXME: What about lowercase? */ + if (STREQN (lexptr, "FALSE", 5)) /* FIXME: What about lowercase? */ { yylval.ulval = 0; lexptr += 5; |