#include "c.h"

static char rcsid[] = "$Id: input.nw,v 2.9 1997/05/30 22:37:13 drh Exp $";

static void pragma(void);
static void resynch(void);

static int bsize;
static unsigned char buffer[MAXLINE+1 + BUFSIZE+1];
unsigned char *cp;      /* current input character */
char *file;             /* current input file name */
char *firstfile;        /* first input file */
unsigned char *limit;   /* points to last character + 1 */
char *line;             /* current line */
int lineno;             /* line number of current line */

void nextline(void) {
  do {
    if (cp >= limit) {
      fillbuf();
      if (cp >= limit)
        cp = limit;
      if (cp == limit)
        return;
    } else {
      lineno++;
      for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++)
        ;
      if (*cp == '#') {
        resynch();
        nextline();
      }
    }
  } while (*cp == '\n' && cp == limit);
}
void fillbuf(void) {
  if (bsize == 0)
    return;
  if (cp >= limit)
    cp = &buffer[MAXLINE+1];
  else
    {
      int n = limit - cp;
      unsigned char *s = &buffer[MAXLINE+1] - n;
      assert(s >= buffer);
      line = (char *)s - ((char *)cp - line);
      while (cp < limit)
        *s++ = *cp++;
      cp = &buffer[MAXLINE+1] - n;
    }
  bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin);
  if (bsize < 0) {
    error("read error\n");
    exit(EXIT_FAILURE);
  }
  limit = &buffer[MAXLINE+1+bsize];
  *limit = '\n';
}
void input_init(int argc, char *argv[]) {
  static int inited;

  if (inited)
    return;
  inited = 1;
  main_init(argc, argv);
  limit = cp = &buffer[MAXLINE+1];
  bsize = -1;
  lineno = 0;
  file = NULL;
  fillbuf();
  if (cp >= limit)
    cp = limit;
  nextline();
}

/* pragma - handle #pragma ref id... */
static void pragma(void) {
  if ((t = gettok()) == ID && strcmp(token, "ref") == 0)
    for (;;) {
      while (*cp == ' ' || *cp == '\t')
        cp++;
      if (*cp == '\n' || *cp == 0)
        break;
      if ((t = gettok()) == ID && tsym) {
        tsym->ref++;
        use(tsym, src);
      }
    }
}

/* resynch - set line number/file name in # n [ "file" ] and #pragma ... */
static void resynch(void) {
  for (cp++; *cp == ' ' || *cp == '\t'; )
    cp++;
  if (limit - cp < MAXLINE)
    fillbuf();
  if (strncmp((char *)cp, "pragma", 6) == 0) {
    cp += 6;
    pragma();
  } else if (*cp >= '0' && *cp <= '9') {
  line:   for (lineno = 0; *cp >= '0' && *cp <= '9'; )
      lineno = 10*lineno + *cp++ - '0';
    lineno--;
    while (*cp == ' ' || *cp == '\t')
      cp++;
    if (*cp == '"') {
      file = (char *)++cp;
      while (*cp && *cp != '"' && *cp != '\n')
        cp++;
      file = stringn(file, (char *)cp - file);
      if (*cp == '\n')
        warning("missing \" in preprocessor line\n");
      if (firstfile == 0)
        firstfile = file;
    }
  } else if (strncmp((char *)cp, "line", 4) == 0) {
    for (cp += 4; *cp == ' ' || *cp == '\t'; )
      cp++;
    if (*cp >= '0' && *cp <= '9')
      goto line;
    if (Aflag >= 2)
      warning("unrecognized control line\n");
  } else if (Aflag >= 2 && *cp != '\n')
    warning("unrecognized control line\n");
  while (*cp)
    if (*cp++ == '\n')
      if (cp == limit + 1)
        nextline();
      else
        break;
}

