diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 28de126aa..37294e0 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2357,7 +2357,6 @@ void mi_cmd_trace_define_variable (char *command, char **argv, int argc) { struct expression *expr; - struct cleanup *back_to; LONGEST initval = 0; struct trace_state_variable *tsv; char *name = 0; @@ -2365,19 +2364,11 @@ mi_cmd_trace_define_variable (char *command, char **argv, int argc) if (argc != 1 && argc != 2) error (_("Usage: -trace-define-variable VARIABLE [VALUE]")); - expr = parse_expression (argv[0]); - back_to = make_cleanup (xfree, expr); - - if (expr->nelts == 3 && expr->elts[0].opcode == OP_INTERNALVAR) - { - struct internalvar *intvar = expr->elts[1].internalvar; - - if (intvar) - name = internalvar_name (intvar); - } + name = argv[0]; + if (*name++ != '$') + error (_("Name of trace variable should start with '$'")); - if (!name || *name == '\0') - error (_("Invalid name of trace variable")); + validate_trace_state_variable_name (name); tsv = find_trace_state_variable (name); if (!tsv) @@ -2387,8 +2378,6 @@ mi_cmd_trace_define_variable (char *command, char **argv, int argc) initval = value_as_long (parse_and_eval (argv[1])); tsv->initial_value = initval; - - do_cleanups (back_to); } void diff --git a/gdb/testsuite/gdb.trace/tsv.exp b/gdb/testsuite/gdb.trace/tsv.exp index 4ea930f..47d66ad 100644 --- a/gdb/testsuite/gdb.trace/tsv.exp +++ b/gdb/testsuite/gdb.trace/tsv.exp @@ -46,14 +46,30 @@ gdb_test "tvariable \$tvar3 = 1234567000000" \ "Trace state variable \\\$tvar3 now has initial value 1234567000000." \ "Init trace state variable to a 64-bit value" +gdb_test "tvariable $" \ + "Must supply a non-empty variable name" \ + "tvariable syntax error, not empty variable name" + gdb_test "tvariable main" \ - "Syntax must be \\\$NAME \\\[ = EXPR \\\]" \ + "Name of trace variable should start with '\\\$'" \ "tvariable syntax error, bad name" +gdb_test "tvariable \$\$" \ + "Syntax must be \\\$NAME \\\[ = EXPR \\\]" \ + "tvariable syntax error, bad name 2" + +gdb_test "tvariable \$123" \ + "\\\$123 is not a valid trace state variable name" \ + "tvariable syntax error, bad name 3" + gdb_test "tvariable \$tvar1 - 93" \ "Syntax must be \\\$NAME \\\[ = EXPR \\\]" \ "tvariable syntax error, not an assignment" +gdb_test "tvariable \$tvar0 = 1 = 1" \ + "Left operand of assignment is not an lvalue\." \ + "tvariable creation fails with invalid expression" + gdb_test "info tvariables" \ "Name\[\t \]+Initial\[\t \]+Current.* \\\$tvar1\[\t \]+0\[\t \]+.* diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index b45863e..540665d 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -362,50 +362,67 @@ delete_trace_state_variable (const char *name) warning (_("No trace variable named \"$%s\", not deleting"), name); } +/* Throws an error if NAME is not valid syntax for a trace state + variable's name. */ + +void +validate_trace_state_variable_name (const char *name) +{ + const char *p; + + if (*name == '\0') + error (_("Must supply a non-empty variable name")); + + /* All digits in the name is reserved for value history + references. */ + for (p = name; isdigit (*p); p++) + ; + if (*p == '\0') + error (_("$%s is not a valid trace state variable name"), name); + + for (p = name; isalnum (*p) || *p == '_'; p++) + ; + if (*p != '\0') + error (_("$%s is not a valid trace state variable name"), name); +} + /* The 'tvariable' command collects a name and optional expression to evaluate into an initial value. */ static void trace_variable_command (char *args, int from_tty) { - struct expression *expr; struct cleanup *old_chain; - struct internalvar *intvar = NULL; LONGEST initval = 0; struct trace_state_variable *tsv; + char *name, *p; if (!args || !*args) - error_no_arg (_("trace state variable name")); + error_no_arg (_("Syntax is $NAME [ = EXPR ]")); - /* All the possible valid arguments are expressions. */ - expr = parse_expression (args); - old_chain = make_cleanup (free_current_contents, &expr); + /* Only allow two syntaxes; "$name" and "$name=value". */ + p = skip_spaces (args); - if (expr->nelts == 0) - error (_("No expression?")); + if (*p++ != '$') + error (_("Name of trace variable should start with '$'")); - /* Only allow two syntaxes; "$name" and "$name=value". */ - if (expr->elts[0].opcode == OP_INTERNALVAR) - { - intvar = expr->elts[1].internalvar; - } - else if (expr->elts[0].opcode == BINOP_ASSIGN - && expr->elts[1].opcode == OP_INTERNALVAR) - { - intvar = expr->elts[2].internalvar; - initval = value_as_long (evaluate_subexpression_type (expr, 4)); - } - else + name = p; + while (isalnum (*p) || *p == '_') + p++; + name = savestring (name, p - name); + old_chain = make_cleanup (xfree, name); + + p = skip_spaces (p); + if (*p != '=' && *p != '\0') error (_("Syntax must be $NAME [ = EXPR ]")); - if (!intvar) - error (_("No name given")); + validate_trace_state_variable_name (name); - if (strlen (internalvar_name (intvar)) <= 0) - error (_("Must supply a non-empty variable name")); + if (*p == '=') + initval = value_as_long (parse_and_eval (++p)); /* If the variable already exists, just change its initial value. */ - tsv = find_trace_state_variable (internalvar_name (intvar)); + tsv = find_trace_state_variable (name); if (tsv) { if (tsv->initial_value != initval) @@ -421,7 +438,7 @@ trace_variable_command (char *args, int from_tty) } /* Create a new variable. */ - tsv = create_trace_state_variable (internalvar_name (intvar)); + tsv = create_trace_state_variable (name); tsv->initial_value = initval; observer_notify_tsv_created (tsv); diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 2e1d83a..61c7212 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -246,6 +246,7 @@ extern void validate_actionline (char **, struct breakpoint *); extern void end_actions_pseudocommand (char *args, int from_tty); extern void while_stepping_pseudocommand (char *args, int from_tty); +extern void validate_trace_state_variable_name (const char *name); extern struct trace_state_variable *find_trace_state_variable (const char *name); extern struct trace_state_variable *create_trace_state_variable (const char *name);