/* Locations for Bison

   Copyright (C) 2002, 2005-2015, 2018-2019 Free Software Foundation,
   Inc.

   This file is part of Bison, the GNU Compiler Compiler.

   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 <config.h>
#include "system.h"

#include <mbfile.h>
#include <mbswidth.h>
#include <quotearg.h>
#include <stdio.h>    /* fileno */
#include <sys/ioctl.h>
#include <sys/stat.h> /* fstat */
#include <termios.h>

#ifdef WINSIZE_IN_PTEM
# include <sys/stream.h>
# include <sys/ptem.h>
#endif

#include "complain.h"
#include "getargs.h"
#include "location.h"

location const empty_loc = EMPTY_LOCATION_INIT;

static int
min_int (int a, int b)
{
  return a < b ? a : b;
}

static int
max_int (int a, int b)
{
  return a >= b ? a : b;
}

/* The terminal width.  Not less than 40.  */
static int
columns (void)
{
  const char *cp = getenv ("COLUMNS");
  int res = 80;
  if (cp && *cp)
    {
      long l = strtol (cp, NULL, 10);
      res = 0 <= l && l <= INT_MAX ? l : INT_MAX;
    }
  else
    {
#ifdef TIOCGWINSZ
      struct winsize ws;
      if (ioctl (STDERR_FILENO, TIOCGWINSZ, &ws) != -1
          && 0 < ws.ws_col && ws.ws_col == (size_t) ws.ws_col)
        res = ws.ws_col;
#endif
    }
  return max_int (res, 40);
}

/* Available screen width.  */
static int screen_width = 80;

/* The ellipsis symbol to use for this locale, and the number of
   screen-columns it uses.  */
static const char *ellipsis = "...";
static int ellipsize = 3;

/* If BUF is null, add BUFSIZE (which in this case must be less than
   INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to
   COLUMN.  If an overflow occurs, return INT_MAX.  */

static inline int
add_column_width (int column, char const *buf, size_t bufsize)
{
  int width
    = buf ? mbsnwidth (buf, bufsize, 0)
    : INT_MAX <= bufsize ? INT_MAX
    : bufsize;
  return column <= INT_MAX - width ? column + width : INT_MAX;
}

static void
boundary_compute (boundary *cur, char const *token, size_t size)
{
  int line = cur->line;
  int column = cur->column;
  int byte = cur->byte;
  char const *p0 = token;
  char const *p = token;
  char const *lim = token + size;

  for (p = token; p < lim; ++p)
    switch (*p)
      {
      case '\n':
        line += line < INT_MAX;
        column = 1;
        byte = 1;
        p0 = p + 1;
        break;

      case '\t':
        column = add_column_width (column, p0, p - p0);
        column = add_column_width (column, NULL, 8 - ((column - 1) & 7));
        p0 = p + 1;
        byte += byte < INT_MAX;
        break;

      default:
        byte += byte < INT_MAX;
        break;
      }
  column = add_column_width (column, p0, p - p0);

  cur->line = line;
  cur->column = column;
  cur->byte = byte;
}


/* Set *LOC and adjust scanner cursor to account for token TOKEN of
   size SIZE.  */

void
location_compute (location *loc, boundary *cur, char const *token, size_t size)
{
  loc->start = *cur;
  boundary_compute (cur, token, size);
  loc->end = *cur;

  if (loc->end.line == INT_MAX && loc->start.line != INT_MAX)
    complain (loc, Wother, _("line number overflow"));
  if (loc->end.column == INT_MAX && loc->start.column != INT_MAX)
    complain (loc, Wother, _("column number overflow"));
  /* TRANSLATORS: we are counting bytes, and there are too many.  */
  if (loc->end.byte == INT_MAX && loc->start.byte != INT_MAX)
    complain (loc, Wother, _("byte number overflow"));
}

static int
boundary_print (boundary const *b, FILE *out)
{
  return fprintf (out, "%s:%d.%d@%d",
                  quotearg_n_style (3, escape_quoting_style, b->file),
                  b->line, b->column, b->byte);
}

int
location_print (location loc, FILE *out)
{
  int res = 0;
  if (trace_flag & trace_locations)
    {
      res += boundary_print (&loc.start, out);
      res += fprintf (out, "-");
      res += boundary_print (&loc.end, out);
    }
  else
    {
      int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0;
      res += fprintf (out, "%s",
                      quotearg_n_style (3, escape_quoting_style, loc.start.file));
      if (0 < loc.start.line)
        {
          res += fprintf (out, ":%d", loc.start.line);
          if (0 < loc.start.column)
            res += fprintf (out, ".%d", loc.start.column);
        }
      if (loc.start.file != loc.end.file)
        {
          res += fprintf (out, "-%s",
                          quotearg_n_style (3, escape_quoting_style,
                                            loc.end.file));
          if (0 < loc.end.line)
            {
              res += fprintf (out, ":%d", loc.end.line);
              if (0 <= end_col)
                res += fprintf (out, ".%d", end_col);
            }
        }
      else if (0 < loc.end.line)
        {
          if (loc.start.line < loc.end.line)
            {
              res += fprintf (out, "-%d", loc.end.line);
              if (0 <= end_col)
                res += fprintf (out, ".%d", end_col);
            }
          else if (0 <= end_col && loc.start.column < end_col)
            res += fprintf (out, "-%d", end_col);
        }
    }

  return res;
}


/* Persistent data used by location_caret to avoid reopening and rereading the
   same file all over for each error.  */
static struct
{
  /* Raw input file.  */
  FILE *file;
  /* Input file as a stream of multibyte characters.  */
  mb_file_t mbfile;
  /* The position within the last file we quoted.  If POS.FILE is non
     NULL, but FILE is NULL, it means this file is special and should
     not be quoted. */
  boundary pos;
  /* Offset in FILE of the current line (i.e., where line POS.LINE
     starts).  */
  size_t offset;
  /* Length of the current line.  */
  int line_len;
  /* Given the initial column to display, the offset (number of
     characters to skip at the beginning of the line). */
  int skip;

  /* Available width to quote the source file.  Eight chars are
     consumed by the left-margin (with line number).  */
  int width;
} caret_info;

void caret_init (void)
{
  screen_width = columns ();
  /* TRANSLATORS: This is used when a line is too long, and is
     displayed truncated.  Use an ellipsis appropriate for your
     language, remembering that "…" (U+2026 HORIZONTAL ELLIPSIS)
     sometimes misdisplays and that "..." (three ASCII periods) is a
     safer choice in some locales.  */
  ellipsis = _("...");
  ellipsize = mbswidth (ellipsis, 0);
}

void
caret_free (void)
{
  if (caret_info.file)
    {
      fclose (caret_info.file);
      caret_info.file = NULL;
    }
}

/* Open FILE for quoting, if needed, and if possible.  Return whether
   the file can quoted. */
static bool
caret_set_file (const char *file)
{
  /* If a different file than before, close and let the rest open
     the new one. */
  if (caret_info.pos.file && caret_info.pos.file != file)
    {
      caret_free ();
      caret_info.pos.file = NULL;
    }
  if (!caret_info.pos.file)
    {
      caret_info.pos.file = file;
      if ((caret_info.file = fopen (caret_info.pos.file, "r")))
        {
          /* If the file is not regular (imagine #line 1 "/dev/stdin"
             in the input file for instance), don't try to quote the
             file.  Keep caret_info.file set so that we don't try to
             open it again, but leave caret_info.file NULL so that we
             don't try to quote it. */
          struct stat buf;
          if (fstat (fileno (caret_info.file), &buf) == 0
              && buf.st_mode & S_IFREG)
            {
              caret_info.pos.line = 1;
              mbf_init (caret_info.mbfile, caret_info.file);
            }
          else
            caret_free ();
        }
    }
  return !!caret_info.file;
}

/* Getc, but smash \r\n as \n.  */
static void
caret_getc_internal (mbchar_t *res)
{
  mbf_getc (*res, caret_info.mbfile);
  if (mb_iseq (*res, '\r'))
    {
      mbchar_t c;
      mbf_getc (c, caret_info.mbfile);
      if (mb_iseq (c, '\n'))
        mb_copy (res, &c);
      else
        mbf_ungetc (c, caret_info.mbfile);
    }
}

#define caret_getc(Var) caret_getc_internal(&Var)

/* Move CARET_INFO (which has a valid FILE) to the line number LINE.
   Compute and cache that line's length in CARET_INFO.LINE_LEN.
   Return whether succesful.*/
static bool
caret_set_line (int line)
{
  /* If the line we want to quote is seekable (the same line as the previous
     location), just seek it. If it was a previous line, we lost track of it,
     so return to the start of file.  */
  if (line < caret_info.pos.line)
    {
      caret_info.pos.line = 1;
      caret_info.offset = 0;
    }
  if (fseek (caret_info.file, caret_info.offset, SEEK_SET))
    return false;

  /* If this is the same line as the previous one, we are done. */
  if (line < caret_info.pos.line)
    return true;

  /* Advance to the line's position, keeping track of the offset.  */
  while (caret_info.pos.line < line)
    {
      mbchar_t c;
      caret_getc (c);
      if (mb_iseof (c))
        /* Something is wrong, that line number does not exist.  */
        return false;
      caret_info.pos.line += mb_iseq (c, '\n');
    }
  caret_info.offset = ftell (caret_info.file);
  caret_info.pos.column = 1;
  /* Reset mbf's internal state.
     FIXME: should be done in mbfile.  */
  caret_info.mbfile.eof_seen = 0;

  /* Find the number of columns of this line.  */
  while (true)
    {
      mbchar_t c;
      caret_getc (c);
      if (mb_iseof (c) || mb_iseq (c, '\n'))
        break;
      boundary_compute (&caret_info.pos, mb_ptr (c), mb_len (c));
    }
  caret_info.line_len = caret_info.pos.column;
  /* Go back to the beginning of line.  */
  if (fseek (caret_info.file, caret_info.offset, SEEK_SET))
    return false;
  /* Reset mbf's internal state.
     FIXME: should be done in mbfile.  */
  caret_info.mbfile.eof_seen = 0;
  caret_info.pos.column = 1;
  return true;
}

/* Compute CARET_INFO.WIDTH and CARET_INFO.SKIP based on the fact that
   the first column to display in the current line is COL.  */
static bool
caret_set_column (int col)
{
  /* Available width.  Eight chars are consumed by the left-margin
     (with line number).  */
  caret_info.width = screen_width - 8;
  caret_info.skip = 0;
  if (caret_info.width < caret_info.line_len)
    {
      /* We cannot quote the whole line.  Make sure we can see the
         beginning of the location.  */
      caret_info.skip = caret_info.width < col ? col - 10 : 0;
    }
  /* If we skip the initial part, we insert "..." before.  */
  if (caret_info.skip)
    caret_info.width -= ellipsize;
  /* If the end of line does not fit, we also need to truncate the
     end, and leave "..." there.  */
  if (caret_info.width < caret_info.line_len - caret_info.skip)
    caret_info.width -= ellipsize;
  return true;
}

void
location_caret (location loc, const char *style, FILE *out)
{
  if (!loc.start.line)
    return;
  if (!caret_set_file (loc.start.file))
    return;
  if (!caret_set_line (loc.start.line))
    return;
  if (!caret_set_column (loc.start.column))
    return;

  const int width = caret_info.width;
  const int skip = caret_info.skip;

  /* Read the actual line.  Don't update the offset, so that we keep a pointer
     to the start of the line.  */
  {
    mbchar_t c;
    caret_getc (c);
    if (!mb_iseof (c))
      {
        /* The last column to highlight.  Only the first line of
           multiline locations are quoted, in which case the ending
           column is the end of line.  Single point locations (with
           equal boundaries) denote the character that they
           follow.  */
        int col_end
          = loc.start.line == loc.end.line
          ? loc.end.column + (loc.start.column == loc.end.column)
          : caret_info.line_len;
        /* Quote the file (at most the first line in the case of
           multiline locations).  */
        {
          fprintf (out, "%5d | %s", loc.start.line, skip ? ellipsis : "");
          /* Whether we opened the style.  If the line is not as
             expected (maybe the file was changed since the scanner
             ran), we might reach the end before we actually saw the
             opening column.  */
          bool opened = false;
          while (!mb_iseof (c) && !mb_iseq (c, '\n'))
            {
              if (caret_info.pos.column == loc.start.column)
                {
                  begin_use_class (style, out);
                  opened = true;
                }
              if (skip < caret_info.pos.column)
                mb_putc (c, out);
              boundary_compute (&caret_info.pos, mb_ptr (c), mb_len (c));
              caret_getc (c);
              if (opened
                  && (caret_info.pos.column == col_end
                      || width < caret_info.pos.column - skip))
                {
                  end_use_class (style, out);
                  opened = false;
                }
              if (width < caret_info.pos.column - skip)
                {
                  fputs (ellipsis, out);
                  break;
                }
            }
          putc ('\n', out);
        }

        /* Print the carets with the same indentation as above.  */
        {
          fprintf (out, "      | %*s",
                   loc.start.column - 1 - skip + (skip ? ellipsize : 0), "");
          begin_use_class (style, out);
          putc ('^', out);
          /* Underlining a multiline location ends with the first
             line.  */
          for (int i = loc.start.column - 1 - skip + 1,
                 i_end = min_int (col_end - 1 - skip, width);
               i < i_end; ++i)
            putc ('~', out);
          end_use_class (style, out);
          putc ('\n', out);
        }
      }
  }
}

void
location_caret_suggestion (location loc, const char *s, FILE *out)
{
  const char *style = "fixit-insert";
  fprintf (out, "      | %*s",
           loc.start.column - 1 - caret_info.skip
           + (caret_info.skip ? ellipsize : 0),
           "");
  begin_use_class (style, out);
  fputs (s, out);
  end_use_class (style, out);
  putc ('\n', out);
}

bool
location_empty (location loc)
{
  return !loc.start.file && !loc.start.line && !loc.start.column
    && !loc.end.file && !loc.end.line && !loc.end.column;
}

void
boundary_set_from_string (boundary *bound, char *str)
{
  /* Must search in reverse since the file name field may contain '.'
     or ':'.  */
  char *at = strrchr (str, '@');
  if (at)
    {
      *at = '\0';
      bound->byte = atoi (at+1);
    }
  {
    char *dot = strrchr (str, '.');
    aver (dot);
    *dot = '\0';
    bound->column = atoi (dot+1);
    if (!at)
      bound->byte = bound->column;
  }
  {
    char *colon = strrchr (str, ':');
    aver (colon);
    *colon = '\0';
    bound->line = atoi (colon+1);
  }
  bound->file = uniqstr_new (str);
}
