#include "c.h"

static char rcsid[] = "$Id: error.nw,v 2.5 1997/05/05 18:19:01 drh Exp $";

static void printtoken(void);
int errcnt   = 0;
int errlimit = 20;
char kind[] = {
#define xx(a,b,c,d,e,f,g) f,
#define yy(a,b,c,d,e,f,g) f,
#include "token.h"
};
int wflag;              /* != 0 to suppress warning messages */

void test(int tok, char set[]) {
  if (t == tok)
    t = gettok();
  else {
    expect(tok);
    skipto(tok, set);
    if (t == tok)
      t = gettok();
  }
}
void expect(int tok) {
  if (t == tok)
    t = gettok();
  else {
    error("syntax error; found");
    printtoken();
    fprint(stderr, " expecting `%k'\n", tok);
  }
}
void error(const char *fmt, ...) {
  va_list ap;

  if (errcnt++ >= errlimit) {
    errcnt = -1;
    error("too many errors\n");
    exit(1);
  }
  va_start(ap, fmt);
  if (firstfile != file && firstfile && *firstfile)
    fprint(stderr, "%s: ", firstfile);
  fprint(stderr, "%w: ", &src);
  vfprint(stderr, NULL, fmt, ap);
  va_end(ap);
}

void skipto(int tok, char set[]) {
  int n;
  char *s;

  assert(set);
  for (n = 0; t != EOI && t != tok; t = gettok()) {
    for (s = set; *s && kind[t] != *s; s++)
      ;
    if (kind[t] == *s)
      break;
    if (n++ == 0)
      error("skipping");
    if (n <= 8)
      printtoken();
    else if (n == 9)
      fprint(stderr, " ...");
  }
  if (n > 8) {
    fprint(stderr, " up to");
    printtoken();
  }
  if (n > 0)
    fprint(stderr, "\n");
}
/* fatal - issue fatal error message and exit */
int fatal(const char *name, const char *fmt, int n) {
  print("\n");
  errcnt = -1;
  error("compiler error in %s--", name);
  fprint(stderr, fmt, n);
  exit(EXIT_FAILURE);
  return 0;
}

/* printtoken - print current token preceeded by a space */
static void printtoken(void) {
  switch (t) {
  case ID: fprint(stderr, " `%s'", token); break;
  case ICON:
    if (*token == '\'') {
      char *s;
  case SCON:      fprint(stderr, " ");
      for (s = token; *s && s - token < 20; s++)
        if (*s < ' ' || *s >= 0177)
          fprint(stderr, "\\%o", *s);
        else
          fprint(stderr, "%c", *s);
      if (*s)
        fprint(stderr, " ...");
      else
        fprint(stderr, "%c", *token);
      break;
    } /* else fall thru */
  case FCON:
    fprint(stderr, " `%S'", token, (char*)cp - token);
    break;
  case '`': case '\'': fprint(stderr, " \"%k\"", t); break;
  default: fprint(stderr, " `%k'", t);
  }
}

/* warning - issue warning error message */
void warning(const char *fmt, ...) {
  va_list ap;

  va_start(ap, fmt);
  if (wflag == 0) {
    errcnt--;
    error("warning: ");
    vfprint(stderr, NULL, fmt, ap);
  }
  va_end(ap);
}
