[PATCHv9 11/14] gdb: create new is_thread_id helper function

Andrew Burgess
2024-03-05T15:24:53Z

This is a refactoring commit that splits the existing parse_thread_id
function into two parts, and then adds a new is_thread_id function.

The core of parse_thread_id is split into parse_thread_id_1, which is
responsible for actually parsing a thread-id. Then parse_thread_id is
responsible for taking a parsed thread-id and validating that it
references an actually existing inferior thread.

The new is_thread_id function also uses parse_thread_id_1, but doesn't
actually check that the inferior thread exists, instead, this new
function simply checks that a string looks like a thread-id.

This commit does not add a use for is_thread_id, this will be added in
the next commit.

This is a refactoring commit, there should be no user visible changes
after this commit.
---
gdb/tid-parse.c | 82 +++++++++++++++++++++++++++++++++++++------------
gdb/tid-parse.h | 8 +++++
2 files changed, 70 insertions(+), 20 deletions(-)

diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index aa1480d7cf0..7f85b94eba4 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -48,40 +48,43 @@ get_positive_number_trailer (const char **pp, int trailer, const char *string)
return num;
}

-/* See tid-parse.h. */
+/* Parse TIDSTR as a per-inferior thread ID, in either INF_NUM.THR_NUM
+ or THR_NUM form, and return a pair, the first item of the pair is
+ INF_NUM and the second item is THR_NUM.

-struct thread_info *
-parse_thread_id (const char *tidstr, const char **end)
+ If TIDSTR does not include an INF_NUM component, then the first item in
+ the pair will be 0 (which is an invalid inferior number), this indicates
+ that TIDSTR references the current inferior.
+
+ This function does not validate the INF_NUM and THR_NUM are actually
+ valid numbers, that is, they might reference inferiors or threads that
+ don't actually exist; this function just splits the string into its
+ component parts.
+
+ If there is an error parsing TIDSTR then this function will raise an
+ exception. */
+
+static std::pair<int, int>
+parse_thread_id_1 (const char *tidstr, const char **end)
{
const char *number = tidstr;
const char *dot, *p1;
- struct inferior *inf;
- int thr_num;
- int explicit_inf_id = 0;
+ int thr_num, inf_num;

dot = strchr (number, '.');

if (dot != NULL)
{
/* Parse number to the left of the dot. */
- int inf_num;
-
p1 = number;
inf_num = get_positive_number_trailer (&p1, '.', number);
if (inf_num == 0)
invalid_thread_id_error (number);
-
- inf = find_inferior_id (inf_num);
- if (inf == NULL)
- error (_("No inferior number '%d'"), inf_num);
-
- explicit_inf_id = 1;
p1 = dot + 1;
}
else
{
- inf = current_inferior ();
-
+ inf_num = 0;
p1 = number;
}

@@ -89,6 +92,32 @@ parse_thread_id (const char *tidstr, const char **end)
if (thr_num == 0)
invalid_thread_id_error (number);

+ if (end != nullptr)
+ *end = p1;
+
+ return { inf_num, thr_num };
+}
+
+/* See tid-parse.h. */
+
+struct thread_info *
+parse_thread_id (const char *tidstr, const char **end)
+{
+ const auto [inf_num, thr_num] = parse_thread_id_1 (tidstr, end);
+
+ inferior *inf;
+ bool explicit_inf_id = false;
+
+ if (inf_num != 0)
+ {
+ inf = find_inferior_id (inf_num);
+ if (inf == nullptr)
+ error (_("No inferior number '%d'"), inf_num);
+ explicit_inf_id = true;
+ }
+ else
+ inf = current_inferior ();
+
thread_info *tp = nullptr;
for (thread_info *it : inf->threads ())
if (it->per_inf_num == thr_num)
@@ -97,7 +126,7 @@ parse_thread_id (const char *tidstr, const char **end)
break;
}

- if (tp == NULL)
+ if (tp == nullptr)
{
if (show_inferior_qualified_tids () || explicit_inf_id)
error (_("Unknown thread %d.%d."), inf->num, thr_num);
@@ -105,14 +134,27 @@ parse_thread_id (const char *tidstr, const char **end)
error (_("Unknown thread %d."), thr_num);
}

- if (end != NULL)
- *end = p1;
-
return tp;
}

/* See tid-parse.h. */

+bool
+is_thread_id (const char *tidstr, const char **end)
+{
+ try
+ {
+ (void) parse_thread_id_1 (tidstr, end);
+ return true;
+ }
+ catch (const gdb_exception_error &)
+ {
+ return false;
+ }
+}
+
+/* See tid-parse.h. */
+
tid_range_parser::tid_range_parser (const char *tidlist,
int default_inferior)
{
diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h
index b7bd920f48a..bba5ae5118c 100644
--- a/gdb/tid-parse.h
+++ b/gdb/tid-parse.h
@@ -36,6 +36,14 @@ extern void ATTRIBUTE_NORETURN invalid_thread_id_error (const char *string);
thrown. */
struct thread_info *parse_thread_id (const char *tidstr, const char **end);

+/* Return true if TIDSTR is pointing to a string that looks like a
+ thread-id. This doesn't mean that TIDSTR identifies a valid thread, but
+ the string does at least look like a valid thread-id. If END is not
+ NULL, parse_thread_id stores the address of the first character after
+ the thread-id into *END. */
+
+bool is_thread_id (const char *tidstr, const char **end);
+
/* Parse a thread ID or a thread range list.

A range will be of the form
--
2.25.4