/***********************************************************************
     "bsc_input.o": BaSiC INPUT functions.
***********************************************************************/

/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************
 $Log: bsc_input.c,v $
 * Revision 1.5  1993/01/12  18:18:44  eps
 * portability issues
 *
 * Revision 1.4  1993/01/12  16:37:07  eps
 * portability issues
 *
 * Revision 1.3  1992/01/14  15:45:44  eps
 * distribution issues
 *
 * Revision 1.2  92/01/14  15:28:30  eps
 * minor bugs
 *
 * Revision 1.1  91/07/11  12:51:06  eps
 * Initial revision
 *
 ***********************************/

/* KJT 08/08/06: fixed handling of stdin */

#ifndef lint
static char rcsid[]= "$Id: bsc_input.c,v 1.5 1993/01/12 18:18:44 eps Exp $";
#endif

/* LINTLIBRARY */

#define bsc_input_IMP

/* KJT 12/02/12: Added*/
#include <string.h>
#include <stdio.h>
#include "bsc_dcls.hh"
#include "lnt_pass.hh"
#include "err_handl.hh"
#include "prg_error.hh"
#include "mem_alloc.hh"
#include "bsc_input.hh"


/* KJT 08/08/06: removed non-constant initialisation to stdin */

PRIVATE FILE *IFP = NULL;	/* input file pointer */

#define IBUF		_IBUF	/* input buffer abbreviation */
#define IBUF_INC	BUFSIZ	/* input buffer increment unit */

/* clears the input buffer */

PRIVATE void
IBclear ()
{
  abort_if(IBUF.size == 0)
  tfree(IBUF.chr);
  IBUF.chr= NULL;
  IBUF.size= 0;
  IBUF.level= 0;
  IBUF.i= 0;
  IBUF.imax= -1;
  IBUF.next_chr= '\0';
}

/* fills the input buffer */

PRIVATE int
IBfill ()
{
  char *p;

  /* KJT 08/08/06: initialise to stdin if not set */
  if (IFP == NULL)
    IFP = stdin;

  abort_if(IBUF.size != 0 || IBUF.eof)
  IBUF.size= IBUF_INC;
  talloc(IBUF.chr, IBUF_INC);
  for (p= fgets(IBUF.chr, IBUF_INC, IFP);
       p != NULL;
       p= fgets(IBUF.chr + IBUF.level, IBUF_INC + 1, IFP))
  {
    IBUF.level+= strlen(IBUF.chr + IBUF.level);
    if (IBUF.level == IBUF.size - 1 &&
	IBUF.chr[IBUF.level - 1] != '\n')
    { IBUF.size+= IBUF_INC;
      trealloc(IBUF.chr, IBUF.size);
    }
    else
      break;
  }
  ++IBUF.lno;
  if (IBUF.level == 0)
  { IBclear();
    IBUF.eof= TRUE;
    return FALSE;
  }
  if (IBUF.chr[IBUF.level - 1] == '\n')
    IBUF.chr[--IBUF.level]= '\0';
  return TRUE;
}

/* returns TRUE if the character is a blank */

#define is_blank(chr)	((chr) == ' ' || (chr) == '\t')

PUBLIC int
is_word (str)
  char *str;
{
  if (str == NULL || *str == '\0')
    return FALSE;
  if (!is_line(str))
    return FALSE;
  for (; *str != '\0'; ++str)
    if (is_blank(*str))
      return FALSE;
  return TRUE;
}

PUBLIC char *
get_word ()
{
  int i, imax;
  char *p;

  if (IBUF.size == 0)
    return NULL;
  if (IBUF.i <= IBUF.imax)
  { if (IBUF.imax == IBUF.level)
      return NULL;
    IBUF.chr[IBUF.imax]= IBUF.next_chr;
    i= imax= IBUF.imax;
  }
  else
    i= imax= IBUF.i;
  while (is_blank(IBUF.chr[imax]))
    ++imax;
  if (IBUF.chr[imax] == '\0')
  { if (IBUF.i <= IBUF.imax)
      IBUF.chr[IBUF.imax]= '\0';
    return NULL;
  }
  p= IBUF.chr + imax;
  for (; imax < IBUF.level; ++imax)
    if (is_blank(IBUF.chr[imax]))
      break;
  IBUF.i= i;
  IBUF.imax= imax;
  IBUF.next_chr= IBUF.chr[IBUF.imax];
  IBUF.chr[IBUF.imax]= '\0';
  return p;
}

PUBLIC int
is_line (str)
  char *str;
{
  /* KJT 12/02/12: Omitted char *strchr(); */

  if (str == NULL)
    return FALSE;
  return strchr(str, '\n') == NULL;
}

PUBLIC char *
get_line ()
{
  if (IBUF.size == 0)
    return NULL;
  if (IBUF.i <= IBUF.imax)
  { if (IBUF.imax == IBUF.level)
      return NULL;
    IBUF.chr[IBUF.imax]= IBUF.next_chr;
    IBUF.i= IBUF.imax;
  }
  IBUF.imax= IBUF.level;
  IBUF.next_chr= IBUF.chr[IBUF.imax];
  return IBUF.chr + IBUF.i;
}

PUBLIC int
unget ()
{
  if (IBUF.size == 0)
    return FALSE;
  if (IBUF.imax < IBUF.i)
    return FALSE;
  IBUF.chr[IBUF.imax]= IBUF.next_chr;
  IBUF.imax= IBUF.i - 1;
  return TRUE;
}

/* returns TRUE if EOL was reached */

PRIVATE int
is_eol ()
{
  int i;

  abort_if(IBUF.size == 0)
  if (IBUF.imax < IBUF.level)
  { if (IBUF.i <= IBUF.imax)
      if (is_blank(IBUF.next_chr))
	i= IBUF.imax + 1;
      else
	return FALSE;
    else
      i= IBUF.i;
    for (; i < IBUF.level; ++i)
      if (is_blank(IBUF.chr[i]))
	continue;
      else
	return FALSE;
  }
  return TRUE;
}

PUBLIC int
new_line ()
{
  if (IBUF.eof)
    return FALSE;
  if (IBUF.lno != 0)
    if (is_eol())
      IBclear();
    else
      return FALSE;
  return IBfill();
}

PUBLIC int
new_file (fp)
  FILE *fp;
{
  if (fp == NULL)
    return FALSE;
  if (IBUF.eof)
    ;
  else if (IBUF.lno == 0)
    ;
  else if (is_eol())
    IBclear();
  else
    return FALSE;
  IBUF.lno= 0;
  IBUF.eof= FALSE;
  IFP= fp;
  return TRUE;
}
