+Wed Dec 30 19:47:13 1992 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y, m2-exp.y (yyreds, yytoks): Remap like other yy* names.
+ * c-exp.y, m2-exp.y (YYDEBUG): Define if MAINTENANCE_CMDS is defined
+ and YYDEBUG is not already defined.
+ * c-exp.y (strncmp): Replace throughout with STREQN, missed
+ them during the previous replacements.
+ * printcmd.c (_initialize_printcmd): Update internal documentation
+ for "set" command to note that the assignment syntax is language
+ dependent.
+ **** start-sanitize-chill ****
+ * ch-exp.y (yyreds, yytoks): Remap like other yy* names.
+ * ch-exp.y (YYDEBUG): Define if MAINTENANCE_CMDS is defined
+ and YYDEBUG is not already defined.
+ * ch-exp.y (GDB_REGNAME, GDB_LAST, GDB_VARIABLE, GDB_ASSIGNMENT,
+ single_assignment_action): New terminals and nonterminal for gdb
+ extensions to chill expression grammer.
+ * ch-exp.y (match_dollar_tokens): Lexer routine to match all
+ tokens that start with '$' (register names, convenience vars, etc).
+ * ch-exp.y (tokentab2): Add GDB_ASSIGNMENT.
+ * ch-exp.y (yylex): Call match_dollar_tokens.
+ **** end-sanitize-chill ****
+
Mon Dec 28 15:00:01 1992 Stu Grossman (grossman at cygnus.com)
* hppah-tdep.c (skip_trampoline_code): Use new macros for
#define yy_yyv c_yyv
#define yyval c_val
#define yylloc c_lloc
+#define yyreds c_reds /* With YYDEBUG defined */
+#define yytoks c_toks /* With YYDEBUG defined */
#define yyss c_yyss /* byacc */
#define yyssp c_yysp /* byacc */
#define yyvs c_yyvs /* byacc */
void
yyerror PARAMS ((char *));
-/* #define YYDEBUG 1 */
+#if MAINTENANCE_CMDS
+#define YYDEBUG 1
+#endif
%}
tokstart = lexptr;
/* See if it is a special token of length 3. */
for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
- if (!strncmp (tokstart, tokentab3[i].operator, 3))
+ if (STREQN (tokstart, tokentab3[i].operator, 3))
{
lexptr += 3;
yylval.opcode = tokentab3[i].opcode;
/* See if it is a special token of length 2. */
for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
- if (!strncmp (tokstart, tokentab2[i].operator, 2))
+ if (STREQN (tokstart, tokentab2[i].operator, 2))
{
lexptr += 2;
yylval.opcode = tokentab2[i].opcode;
if (*tokstart == '$') {
for (c = 0; c < NUM_REGS; c++)
if (namelen - 1 == strlen (reg_names[c])
- && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+ && STREQN (tokstart + 1, reg_names[c], namelen - 1))
{
yylval.lval = c;
return REGNAME;
}
for (c = 0; c < num_std_regs; c++)
if (namelen - 1 == strlen (std_regs[c].name)
- && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+ && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
{
yylval.lval = std_regs[c].regnum;
return REGNAME;
switch (namelen)
{
case 8:
- if (!strncmp (tokstart, "unsigned", 8))
+ if (STREQN (tokstart, "unsigned", 8))
return UNSIGNED;
if (current_language->la_language == language_cplus
- && !strncmp (tokstart, "template", 8))
+ && STREQN (tokstart, "template", 8))
return TEMPLATE;
- if (!strncmp (tokstart, "volatile", 8))
+ if (STREQN (tokstart, "volatile", 8))
return VOLATILE_KEYWORD;
break;
case 6:
- if (!strncmp (tokstart, "struct", 6))
+ if (STREQN (tokstart, "struct", 6))
return STRUCT;
- if (!strncmp (tokstart, "signed", 6))
+ if (STREQN (tokstart, "signed", 6))
return SIGNED_KEYWORD;
- if (!strncmp (tokstart, "sizeof", 6))
+ if (STREQN (tokstart, "sizeof", 6))
return SIZEOF;
break;
case 5:
if (current_language->la_language == language_cplus
- && !strncmp (tokstart, "class", 5))
+ && STREQN (tokstart, "class", 5))
return CLASS;
- if (!strncmp (tokstart, "union", 5))
+ if (STREQN (tokstart, "union", 5))
return UNION;
- if (!strncmp (tokstart, "short", 5))
+ if (STREQN (tokstart, "short", 5))
return SHORT;
- if (!strncmp (tokstart, "const", 5))
+ if (STREQN (tokstart, "const", 5))
return CONST_KEYWORD;
break;
case 4:
- if (!strncmp (tokstart, "enum", 4))
+ if (STREQN (tokstart, "enum", 4))
return ENUM;
- if (!strncmp (tokstart, "long", 4))
+ if (STREQN (tokstart, "long", 4))
return LONG;
if (current_language->la_language == language_cplus
- && !strncmp (tokstart, "this", 4))
+ && STREQN (tokstart, "this", 4))
{
static const char this_name[] =
{ CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
}
break;
case 3:
- if (!strncmp (tokstart, "int", 3))
+ if (STREQN (tokstart, "int", 3))
return INT_KEYWORD;
break;
default:
#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 */
int
yyparse PARAMS ((void));
-/* #define YYDEBUG 1 */
+#if MAINTENANCE_CMDS
+#define YYDEBUG 1
+#endif
%}
%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
%type <voidval> case_label_specification
%type <voidval> buffer_location
+%type <voidval> single_assignment_action
+
%%
/* Z.200, 5.3.1 */
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 */
{
write_exp_elt_opcode (BINOP_BITWISE_XOR);
}
+ | single_assignment_action
+ {
+ $$ = 0; /* FIXME */
+ }
;
/* Z.200, 5.3.4 */
;
+/* 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. */
}
}
+/* 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 ()
{
static const struct token tokentab2[] =
{
+ { ":=", GDB_ASSIGNMENT },
{ "//", SLASH_SLASH },
{ "/=", NOTEQUAL },
{ "<=", LEQ },
return (0);
case '.':
case '=':
- case ':':
case ';':
case '!':
case '+':
return (*lexptr++);
}
/* Look for characters which start a particular kind of multicharacter
- token, such as a character literal. */
+ token, such as a character literal, register name, convenience
+ variable name, etc. */
switch (*lexptr)
{
case 'C':
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);
/* 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);
/* 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);
/* See if it is a special token of length 2. */
for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
{
- if (strncmp (lexptr, tokentab2[i].operator, 2) == 0)
+ if (STREQN (lexptr, tokentab2[i].operator, 2))
{
lexptr += 2;
return (tokentab2[i].token);
would already have found it. */
switch (*lexptr)
{
+ case ':':
case '/':
case '<':
case '>':
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;
#define yy_yyv m2_yyv
#define yyval m2_val
#define yylloc m2_lloc
+#define yyreds m2_reds /* With YYDEBUG defined */
+#define yytoks m2_toks /* With YYDEBUG defined */
#define yyss m2_yyss /* byacc */
#define yyssp m2_yysp /* byacc */
#define yyvs m2_yyvs /* byacc */
static struct block *modblock=0;
#endif
-/* #define YYDEBUG 1 */
+#if MAINTENANCE_CMDS
+#define YYDEBUG 1
+#endif
+
%}
/* Although the yacc "value" of an expression is not used,
/* See if it is a special token of length 2 */
for( i = 0 ; i < sizeof tokentab2 / sizeof tokentab2[0] ; i++)
- if(!strncmp(tokentab2[i].name, tokstart, 2))
+ if(STREQN(tokentab2[i].name, tokstart, 2))
{
lexptr += 2;
return tokentab2[i].token;
if (*tokstart == '$') {
for (c = 0; c < NUM_REGS; c++)
if (namelen - 1 == strlen (reg_names[c])
- && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+ && STREQN (tokstart + 1, reg_names[c], namelen - 1))
{
yylval.lval = c;
return REGNAME;
}
for (c = 0; c < num_std_regs; c++)
if (namelen - 1 == strlen (std_regs[c].name)
- && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+ && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
{
yylval.lval = std_regs[c].regnum;
return REGNAME;
/* Lookup special keywords */
for(i = 0 ; i < sizeof(keytab) / sizeof(keytab[0]) ; i++)
- if(namelen == strlen(keytab[i].keyw) && !strncmp(tokstart,keytab[i].keyw,namelen))
+ if(namelen == strlen(keytab[i].keyw) && STREQN(tokstart,keytab[i].keyw,namelen))
return keytab[i].token;
yylval.sval.ptr = tokstart;
else
{
/* Built-in BOOLEAN type. This is sort of a hack. */
- if(!strncmp(tokstart,"TRUE",4))
+ if(STREQN(tokstart,"TRUE",4))
{
yylval.ulval = 1;
return M2_TRUE;
}
- else if(!strncmp(tokstart,"FALSE",5))
+ else if(STREQN(tokstart,"FALSE",5))
{
yylval.ulval = 0;
return M2_FALSE;
This is useful in user-defined commands.");
add_prefix_cmd ("set", class_vars, set_command,
-"Perform an assignment VAR = EXP.\n\
-You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\
-(names starting with $), a register (a few standard names starting with $),\n\
-or an actual variable in the program being debugged. EXP is any expression.\n\
+"Evaluate expression EXP and assign result to variable VAR, using assignment\n\
+syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
+example). VAR may be a debugger \"convenience\" variable (names starting\n\
+with $), a register (a few standard names starting with $), or an actual\n\
+variable in the program being debugged. EXP is any valid expression.\n\
Use \"set variable\" for variables with names identical to set subcommands.\n\
\nWith a subcommand, this command modifies parts of the gdb environment.\n\
You can see these environment settings with the \"show\" command.",
history, if it is not void.");
add_cmd ("variable", class_vars, set_command,
- "Perform an assignment VAR = EXP.\n\
-You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\
-(names starting with $), a register (a few standard names starting with $),\n\
-or an actual variable in the program being debugged. EXP is any expression.\n\
+"Evaluate expression EXP and assign result to variable VAR, using assignment\n\
+syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
+example). VAR may be a debugger \"convenience\" variable (names starting\n\
+with $), a register (a few standard names starting with $), or an actual\n\
+variable in the program being debugged. EXP is any valid expression.\n\
This may usually be abbreviated to simply \"set\".",
&setlist);