/*
    Clif - A C-like Interpreter Framework
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997 T. Hruz, L. Koren
    1998 L. Koren

    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 2 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, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

/* \verbatim{input_c.tex} */

/*
 * input.c
 *
 * Initialization of the main compiler
 * and redefinition of its input functions.
 * Different input function are used during
 * synchronous and asynchronous interrupt
 * handling.
 */

#include <stdio.h>
#include <fcntl.h>
#include "global.h"
#include "lex_t.h"
#include "input.h"

extern FILEATTR pf, spf[];
#ifndef FLEX_SCANNER
extern int yylineno;
extern int yytchar;
extern char *yysptr, yysbuf[];

extern int getcx PROTO((FILE *));
static int buf_pointer = 0;
#else
extern FILE *yyin;
#endif

#define U(x) x

int (*input) PROTO((void));

char string_resume[]="resume;"; /* Buffer for input by return 
				 * from asynchronous interrupt.
				 */
extern int no_compile_only;	/* Flag in the case of errors or */
				/* compile only. */
extern int handle_main;		/* If set, compiler like behavior. */
extern int source_line_number;
				/* Source line number. Detecting if */
				/* the current line was already */
				/* printed. Using in error messages. */
extern void exit_file_scope PROTO((void));

#ifndef FLEX_SCANNER
/*
 * Redefinition of the input for the main compiler.
 */
int 
input_komp ()
{
#ifdef DEBUG_INTER 
  printfx("in front of getc in input\n");
#endif
  yytchar=yysptr>yysbuf?U(*--yysptr):getcx(pf.fp);
#ifdef DEBUG_INTER 
  printfx("behind of getc in input, read character %c - %x\n",
	  yytchar, yytchar);
#endif
  if(yytchar == '\n')		/* LF */
    {
      yylineno++;
      spf[s].line_counter++;
      char_counter = 0;
      line_buf[0] = 0;
    }
  if(yytchar == EOF)		/* Is current char EOF? */
    { 
      if (s > 0)
	{
	  spf[s].line_counter = 1; /* Counting lines from beginning. */
	  source_line_number = 0; /* Resetting line number in the */
				  /* presence of errors. */
	  fclose (spf[s].fp); 
	  exit_file_scope ();
	  s = s - 1;
	  if (! s && ! no_compile_only)
	    return 0;

	  /* If we want compiler-like behavior, don't switch to
	     stdin. */
	  if (! s && handle_main)
	    return 0;
	  
	  pf = spf[s];		/* Move to the next opened file. */
	}
#ifdef DEBUG_INTER 
      printfx ("in front of the second getc in input\n");
#endif
      yytchar = yysptr>yysbuf?U(*--yysptr):getcx(pf.fp); /* The first char */
#ifdef DEBUG_INTER 
      printfx ("behind of the second getc in input, read character %c - %x\n",
	       yytchar, yytchar);
#endif
    }
  return (yytchar);
}

/*
 * Redefinition of the input for the main compiler.
 * It is used during an interrupt.
 */
int
input_std ()
{
#ifdef DEBUG_INTER 
  printfx ("in front of the third getc in input\n");
#endif
  yytchar = yysptr>yysbuf?U(*--yysptr):getcx(stdin);
#ifdef DEBUG_INTER 
  printfx ("behind of the third getc in input, read character %c - %x\n",
	   yytchar, yytchar);
#endif
  if (yytchar == '\n')		/* LF */
    {
      yylineno++;
      spf[s].line_counter++;
      char_counter = 0;
      line_buf[0] = 0;
    }
  
#ifndef NOT_MSWIN_AND_YES_DOS
  if (HANDLER_TEST)
    {
      HANDLER_SET;
      input = input_buf;
      buf_pointer = 0;
      return (input_buf());
    }
#endif
  return (yytchar);
}
	
/*
 * Redefinition of the input for the main compiler.
 * It is used by return from an interrupt.
 */
int
input_buf ()   
{
  yytchar = yysptr>yysbuf?U(*--yysptr):string_resume[buf_pointer++];
  if (yytchar == '\n')		/* LF */
    {
      yylineno++;
      spf[s].line_counter++;
      char_counter = 0;
      line_buf[0] = 0;
    }
  return (yytchar);
}

#else


int
terminate_buffer ()
{
  fclose (spf[s].fp);
  spf[s].fp = NULL;
  spf[s].name = NULL;
  spf[s--].line_counter = 1;
  source_line_number = 0;
  exit_file_scope ();

  /*  Do not switch to stdin, if the user wants compiler-like
      behavior.  */
  if (! s && handle_main)
    return 1;

  return (! s && ! no_compile_only);
}

#endif /* FLEX_SCANNER */

/*
 * Initialization of the main compiler input.
 */
int
init_input (argc1, argv1)
  int argc1;
  char *argv1[];
{
  int b;

#ifndef FLEX_SCANNER
  input = input_komp;
#endif
  s = argc1 - 1;
  spf[0].fp = stdin;
  spf[0].name = "stdin";
  spf[0].line_counter = 1;
  for (b = 1; b < argc1; b++)                       

				/* File opening and storing their pointer. */ 

    {
      spf[argc1 - b].fp = fopen(argv1[b],"r");
      spf[argc1 - b].name = argv1[b];
      spf[argc1 - b].line_counter = 1;
      if (spf[argc1-b].fp == NULL)
	{
	  s = argc1 - b;
	  error_message (7001);
	  return (-1);
	}	
    }
/* 
 * Takes the first file pointer from the stack. 
 */
#ifdef FLEX_SCANNER
  yyin = spf[s].fp;
#else
  pf.fp = spf[s].fp;
#endif
  return 0;
}

/* \verbatim */
