/* TID parsing for GDB, the GNU debugger.

   Copyright (C) 2015-2016 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 thread_info *tp;
  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);

  ALL_THREADS (tp)
    {
      if (ptid_get_pid (tp->ptid) == inf->pid
	  && tp->per_inf_num == thr_num)
	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:
      return *m_cur_tok == '\0';
    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_const (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;
}

/* See gdbthread.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);
  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;
}
