123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- /* TID parsing for GDB, the GNU debugger.
- Copyright (C) 2015-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "tid-parse.h"
- #include "inferior.h"
- #include "gdbthread.h"
- #include <ctype.h>
- /* See tid-parse.h. */
- void ATTRIBUTE_NORETURN
- invalid_thread_id_error (const char *string)
- {
- error (_("Invalid thread ID: %s"), string);
- }
- /* Wrapper for get_number_trailer that throws an error if we get back
- a negative number. We'll see a negative value if the number is
- stored in a negative convenience variable (e.g., $minus_one = -1).
- STRING is the parser string to be used in the error message if we
- do get back a negative number. */
- static int
- get_positive_number_trailer (const char **pp, int trailer, const char *string)
- {
- int num;
- num = get_number_trailer (pp, trailer);
- if (num < 0)
- error (_("negative value: %s"), string);
- return num;
- }
- /* See tid-parse.h. */
- struct thread_info *
- parse_thread_id (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;
- 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 ();
- p1 = number;
- }
- thr_num = get_positive_number_trailer (&p1, 0, number);
- if (thr_num == 0)
- invalid_thread_id_error (number);
- thread_info *tp = nullptr;
- for (thread_info *it : inf->threads ())
- if (it->per_inf_num == thr_num)
- {
- tp = it;
- break;
- }
- if (tp == NULL)
- {
- if (show_inferior_qualified_tids () || explicit_inf_id)
- error (_("Unknown thread %d.%d."), inf->num, thr_num);
- else
- error (_("Unknown thread %d."), thr_num);
- }
- if (end != NULL)
- *end = p1;
- return tp;
- }
- /* See tid-parse.h. */
- tid_range_parser::tid_range_parser (const char *tidlist,
- int default_inferior)
- {
- init (tidlist, default_inferior);
- }
- /* See tid-parse.h. */
- void
- tid_range_parser::init (const char *tidlist, int default_inferior)
- {
- m_state = STATE_INFERIOR;
- m_cur_tok = tidlist;
- m_inf_num = 0;
- m_qualified = false;
- m_default_inferior = default_inferior;
- }
- /* See tid-parse.h. */
- bool
- tid_range_parser::finished () const
- {
- switch (m_state)
- {
- case STATE_INFERIOR:
- /* Parsing is finished when at end of string or null string,
- or we are not in a range and not in front of an integer, negative
- integer, convenience var or negative convenience var. */
- return (*m_cur_tok == '\0'
- || !(isdigit (*m_cur_tok)
- || *m_cur_tok == '$'
- || *m_cur_tok == '*'));
- case STATE_THREAD_RANGE:
- case STATE_STAR_RANGE:
- return m_range_parser.finished ();
- }
- gdb_assert_not_reached ("unhandled state");
- }
- /* See tid-parse.h. */
- const char *
- tid_range_parser::cur_tok () const
- {
- switch (m_state)
- {
- case STATE_INFERIOR:
- return m_cur_tok;
- case STATE_THREAD_RANGE:
- case STATE_STAR_RANGE:
- return m_range_parser.cur_tok ();
- }
- gdb_assert_not_reached ("unhandled state");
- }
- void
- tid_range_parser::skip_range ()
- {
- gdb_assert (m_state == STATE_THREAD_RANGE
- || m_state == STATE_STAR_RANGE);
- m_range_parser.skip_range ();
- init (m_range_parser.cur_tok (), m_default_inferior);
- }
- /* See tid-parse.h. */
- bool
- tid_range_parser::tid_is_qualified () const
- {
- return m_qualified;
- }
- /* Helper for tid_range_parser::get_tid and
- tid_range_parser::get_tid_range. Return the next range if THR_END
- is non-NULL, return a single thread ID otherwise. */
- bool
- tid_range_parser::get_tid_or_range (int *inf_num,
- int *thr_start, int *thr_end)
- {
- if (m_state == STATE_INFERIOR)
- {
- const char *p;
- const char *space;
- space = skip_to_space (m_cur_tok);
- p = m_cur_tok;
- while (p < space && *p != '.')
- p++;
- if (p < space)
- {
- const char *dot = p;
- /* Parse number to the left of the dot. */
- p = m_cur_tok;
- m_inf_num = get_positive_number_trailer (&p, '.', m_cur_tok);
- if (m_inf_num == 0)
- return 0;
- m_qualified = true;
- p = dot + 1;
- if (isspace (*p))
- return false;
- }
- else
- {
- m_inf_num = m_default_inferior;
- m_qualified = false;
- p = m_cur_tok;
- }
- m_range_parser.init (p);
- if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
- {
- /* Setup the number range parser to return numbers in the
- whole [1,INT_MAX] range. */
- m_range_parser.setup_range (1, INT_MAX, skip_spaces (p + 1));
- m_state = STATE_STAR_RANGE;
- }
- else
- m_state = STATE_THREAD_RANGE;
- }
- *inf_num = m_inf_num;
- *thr_start = m_range_parser.get_number ();
- if (*thr_start < 0)
- error (_("negative value: %s"), m_cur_tok);
- if (*thr_start == 0)
- {
- m_state = STATE_INFERIOR;
- return false;
- }
- /* If we successfully parsed a thread number or finished parsing a
- thread range, switch back to assuming the next TID is
- inferior-qualified. */
- if (!m_range_parser.in_range ())
- {
- m_state = STATE_INFERIOR;
- m_cur_tok = m_range_parser.cur_tok ();
- if (thr_end != NULL)
- *thr_end = *thr_start;
- }
- /* 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
- && (m_state == STATE_THREAD_RANGE
- || m_state == STATE_STAR_RANGE))
- {
- *thr_end = m_range_parser.end_value ();
- skip_range ();
- }
- return (*inf_num != 0 && *thr_start != 0);
- }
- /* See tid-parse.h. */
- bool
- tid_range_parser::get_tid_range (int *inf_num,
- int *thr_start, int *thr_end)
- {
- gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
- return get_tid_or_range (inf_num, thr_start, thr_end);
- }
- /* See tid-parse.h. */
- bool
- tid_range_parser::get_tid (int *inf_num, int *thr_num)
- {
- gdb_assert (inf_num != NULL && thr_num != NULL);
- return get_tid_or_range (inf_num, thr_num, NULL);
- }
- /* See tid-parse.h. */
- bool
- tid_range_parser::in_star_range () const
- {
- return m_state == STATE_STAR_RANGE;
- }
- bool
- tid_range_parser::in_thread_range () const
- {
- return m_state == STATE_THREAD_RANGE;
- }
- /* See tid-parse.h. */
- int
- tid_is_in_list (const char *list, int default_inferior,
- int inf_num, int thr_num)
- {
- if (list == NULL || *list == '\0')
- return 1;
- tid_range_parser parser (list, default_inferior);
- if (parser.finished ())
- invalid_thread_id_error (parser.cur_tok ());
- while (!parser.finished ())
- {
- int tmp_inf, tmp_thr_start, tmp_thr_end;
- if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
- invalid_thread_id_error (parser.cur_tok ());
- if (tmp_inf == inf_num
- && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
- return 1;
- }
- return 0;
- }
|