+2016-01-15 Pedro Alves <palves@redhat.com>
+
+ * NEWS: Mention star wildcard ranges.
+ * cli/cli-utils.c (get_number_or_range): Check state->in_range first.
+ (number_range_setup_range): New function.
+ * cli/cli-utils.h (number_range_setup_range): New declaration.
+ * thread.c (thread_apply_command): Support star TID ranges.
+ * tid-parse.c (tid_range_parser_finished)
+ (tid_range_parser_string, tid_range_parser_skip)
+ (get_tid_or_range, get_tid_or_range): Handle
+ TID_RANGE_STATE_STAR_RANGE.
+ (tid_range_parser_star_range): New function.
+ * tid-parse.h (enum tid_range_state) <TID_RANGE_STATE_STAR_RANGE>:
+ New value.
+ (tid_range_parser_star_range): New declaration.
+
2016-01-15 Pedro Alves <palves@redhat.com>
* thread.c (thread_apply_command): Use the tid range parser to
[Switching to thread 2.1 (Thread 0x7ffff7fc2740 (LWP 8157))] (running)
(gdb)
+* In commands that accept a list of thread IDs, you can now refer to
+ all threads of an inferior using a star wildcard. GDB accepts
+ "INF_NUM.*", to refer to all threads of inferior INF_NUM, and "*" to
+ refer to all threads of the current inferior. For example, "info
+ threads 2.*".
+
* You can use "info threads -gid" to display the global thread ID of
all threads.
int
get_number_or_range (struct get_number_or_range_state *state)
{
- if (*state->string != '-')
+ if (state->in_range)
+ {
+ /* All number-parsing has already been done. Return the next
+ integer value (one greater than the saved previous value).
+ Do not advance the token pointer until the end of range is
+ reached. */
+
+ if (++state->last_retval == state->end_value)
+ {
+ /* End of range reached; advance token pointer. */
+ state->string = state->end_ptr;
+ state->in_range = 0;
+ }
+ }
+ else if (*state->string != '-')
{
/* Default case: state->string is pointing either to a solo
number, or to the first number of a range. */
state->in_range = 1;
}
}
- else if (! state->in_range)
- error (_("negative value"));
else
- {
- /* state->string points to the '-' that betokens a range. All
- number-parsing has already been done. Return the next
- integer value (one greater than the saved previous value).
- Do not advance the token pointer until the end of range
- is reached. */
-
- if (++state->last_retval == state->end_value)
- {
- /* End of range reached; advance token pointer. */
- state->string = state->end_ptr;
- state->in_range = 0;
- }
- }
+ error (_("negative value"));
state->finished = *state->string == '\0';
return state->last_retval;
}
+/* See documentation in cli-utils.h. */
+
+void
+number_range_setup_range (struct get_number_or_range_state *state,
+ int start_value, int end_value, const char *end_ptr)
+{
+ gdb_assert (start_value > 0);
+
+ state->in_range = 1;
+ state->end_ptr = end_ptr;
+ state->last_retval = start_value - 1;
+ state->end_value = end_value;
+}
+
/* Accept a number and a string-form list of numbers such as is
accepted by get_number_or_range. Return TRUE if the number is
in the list.
extern int get_number_or_range (struct get_number_or_range_state *state);
+/* Setups STATE such that get_number_or_range returns numbers in range
+ START_VALUE to END_VALUE. When get_number_or_range returns
+ END_VALUE, the STATE string is advanced to END_PTR. */
+
+extern void number_range_setup_range (struct get_number_or_range_state *state,
+ int start_value, int end_value,
+ const char *end_ptr);
+
/* Accept a number and a string-form list of numbers such as is
accepted by get_number_or_range. Return TRUE if the number is
in the list.
+2016-01-15 Pedro Alves <palves@redhat.com>
+
+ * gdb.texinfo (Threads) <thread ID lists>: Document star ranges.
+
2016-01-13 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Threads): Document the $_gthread convenience
@anchor{thread ID lists}
@cindex thread ID lists
Some commands accept a space-separated @dfn{thread ID list} as
-argument. A list element can be a thread ID as shown in the first
-field of the @samp{info threads} display, with or without an inferior
-qualifier (e.g., @samp{2.1} or @samp{1}); or can be a range of thread
-numbers, again with or without an inferior qualifier, as in
-@var{inf1}.@var{thr1}-@var{thr2} or @var{thr1}-@var{thr2} (e.g.,
-@samp{1.2-4} or @samp{2-4}). For example, if the current inferior is
-1, the thread list @samp{1 2-3 4.5 6.7-9} includes threads 1 to 3 of
-inferior 1, thread 5 of inferior 4 and threads 7 to 9 of inferior 6.
-That is, in expanded qualified form, the same as @samp{1.1 1.2 1.3 4.5
-6.7 6.8 6.9}.
+argument. A list element can be:
+
+@enumerate
+@item
+A thread ID as shown in the first field of the @samp{info threads}
+display, with or without an inferior qualifier. E.g., @samp{2.1} or
+@samp{1}.
+
+@item
+A range of thread numbers, again with or without an inferior
+qualifier, as in @var{inf}.@var{thr1}-@var{thr2} or
+@var{thr1}-@var{thr2}. E.g., @samp{1.2-4} or @samp{2-4}.
+
+@item
+All threads of an inferior, specified with a star wildcard, with or
+without an inferior qualifier, as in @var{inf}.@code{*} (e.g.,
+@samp{1.*}) or @code{*}. The former refers to all threads of the
+given inferior, and the latter form without an inferior qualifier
+refers to all threads of the current inferior.
+
+@end enumerate
+
+For example, if the current inferior is 1, and inferior 7 has one
+thread with ID 7.1, the thread list @samp{1 2-3 4.5 6.7-9 7.*}
+includes threads 1 to 3 of inferior 1, thread 5 of inferior 4, threads
+7 to 9 of inferior 6 and all threads of inferior 7. That is, in
+expanded qualified form, the same as @samp{1.1 1.2 1.3 4.5 6.7 6.8 6.9
+7.1}.
+
@anchor{global thread numbers}
@cindex global thread number
+2016-01-15 Pedro Alves <palves@redhat.com>
+
+ * gdb.multi/tids.exp: Test star wildcard ranges.
+
2016-01-15 Pedro Alves <palves@redhat.com>
* gdb.multi/tids.exp (thr_apply_info_thr_error): Remove "p 1234"
"warning: Unknown thread 30.1" \
"thread apply \$inf.1"
+ # Star ranges.
+
+ thr_apply_info_thr "1.*" \
+ "1.1 1.2 1.3"
+
+ thr_apply_info_thr "*" \
+ "1.1 1.2 1.3"
+
+ thr_apply_info_thr "1.* 2.1" \
+ "1.1 1.2 1.3 2.1"
+
+ thr_apply_info_thr "2.1 1.*" \
+ "1.1 1.2 1.3 2.1" \
+ "2.1 1.1 1.2 1.3"
+
+ thr_apply_info_thr "1.* 2.*" \
+ "1.1 1.2 1.3 2.1 2.2 2.3"
+
+ thr_apply_info_thr "2.* 1.*" \
+ "1.1 1.2 1.3 2.1 2.2 2.3" \
+ "2.1 2.2 2.3 1.1 1.2 1.3"
+
+ # There's no inferior 3, but "info threads" treats the thread list
+ # as a filter, so it's OK. "thread apply" complains about the
+ # unknown inferior through.
+ info_threads "1.1 3.*" \
+ "1.1"
+ gdb_test "thread apply 1.1 3.* p 1" \
+ "Thread 1.1.*warning: Unknown inferior 3"
+
# Now test a set of invalid thread IDs/ranges.
thr_apply_info_thr_invalid "1." \
thr_apply_info_thr_error "${prefix}-\$one" "negative value"
thr_apply_info_thr_error "${prefix}\$minus_one" \
"negative value: ${prefix_re}\\\$minus_one"
+
+ thr_apply_info_thr_error "${prefix}1-*" "inverted range"
+ thr_apply_info_thr_invalid "${prefix}*1"
+ thr_apply_info_thr_invalid "${prefix}*foo"
+ thr_apply_info_thr_invalid "${prefix}foo*"
}
# Check that a valid thread ID list with a missing command errors
gdb_test "thread apply 1-2" $output
gdb_test "thread apply 1.1-2" $output
gdb_test "thread apply $thr" $output
+ gdb_test "thread apply 1.*" $output
}
# Check that we do parse the inferior number and don't confuse it.
inf = find_inferior_id (inf_num);
if (inf != NULL)
tp = find_thread_id (inf, thr_num);
+
+ if (tid_range_parser_star_range (&parser))
+ {
+ if (inf == NULL)
+ {
+ warning (_("Unknown inferior %d"), inf_num);
+ tid_range_parser_skip (&parser);
+ continue;
+ }
+
+ /* No use looking for threads past the highest thread number
+ the inferior ever had. */
+ if (thr_num >= inf->highest_thread_num)
+ tid_range_parser_skip (&parser);
+
+ /* Be quiet about unknown threads numbers. */
+ if (tp == NULL)
+ continue;
+ }
+
if (tp == NULL)
{
if (show_inferior_qualified_tids ()
case TID_RANGE_STATE_INFERIOR:
return *parser->string == '\0';
case TID_RANGE_STATE_THREAD_RANGE:
+ case TID_RANGE_STATE_STAR_RANGE:
return parser->range_parser.finished;
}
case TID_RANGE_STATE_INFERIOR:
return parser->string;
case TID_RANGE_STATE_THREAD_RANGE:
+ case TID_RANGE_STATE_STAR_RANGE:
return parser->range_parser.string;
}
void
tid_range_parser_skip (struct tid_range_parser *parser)
{
- gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE)
+ gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE
+ || parser->state == TID_RANGE_STATE_STAR_RANGE)
&& parser->range_parser.in_range);
tid_range_parser_init (parser, parser->range_parser.end_ptr,
}
init_number_or_range (&parser->range_parser, p);
- parser->state = TID_RANGE_STATE_THREAD_RANGE;
+ if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
+ {
+ /* Setup the number range parser to return numbers in the
+ whole [1,INT_MAX] range. */
+ number_range_setup_range (&parser->range_parser, 1, INT_MAX,
+ skip_spaces_const (p + 1));
+ parser->state = TID_RANGE_STATE_STAR_RANGE;
+ }
+ else
+ parser->state = TID_RANGE_STATE_THREAD_RANGE;
}
*inf_num = parser->inf_num;
/* If we're midway through a range, and the caller wants the end
value, return it and skip to the end of the range. */
- if (thr_end != NULL && parser->state == TID_RANGE_STATE_THREAD_RANGE)
+ if (thr_end != NULL
+ && (parser->state == TID_RANGE_STATE_THREAD_RANGE
+ || parser->state == TID_RANGE_STATE_STAR_RANGE))
{
*thr_end = parser->range_parser.end_value;
tid_range_parser_skip (parser);
/* See tid-parse.h. */
+int
+tid_range_parser_star_range (struct tid_range_parser *parser)
+{
+ return parser->state == TID_RANGE_STATE_STAR_RANGE;
+}
+
+/* See gdbthread.h. */
+
int
tid_is_in_list (const char *list, int default_inferior,
int inf_num, int thr_num)
/* Parsing the thread number or thread number range. */
TID_RANGE_STATE_THREAD_RANGE,
+
+ /* Parsing a star wildcard thread range. E.g., "1.*". */
+ TID_RANGE_STATE_STAR_RANGE,
};
/* An object of this type is passed to tid_range_parser_get_tid. It
int *inf_num,
int *thr_start, int *thr_end);
+/* Returns non-zero if processing a star wildcard (e.g., "1.*")
+ range. */
+extern int tid_range_parser_star_range (struct tid_range_parser *parser);
+
/* Returns non-zero if parsing has completed. */
extern int tid_range_parser_finished (struct tid_range_parser *parser);