/*
    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.

*/

/*
 * sig-svr3.c
 *
 * Functions for framework interrupt handling and fatal error
 * handling.
 */

#include <stdio.h>
#include "global.h"
#include "config.h"

/* \verbatim{sig_svr3_c_interrupt_handler.tex} */

#include <signal.h>
#include <termio.h>
#include <fcntl.h>
#include <setjmp.h>

#define OFF(x, y) (x) & (~(y))
#define ON(x, y) (x) | (y)
#define SPACE 0x20
#define NL '\n'

int handler = 0;
int handle_fd;
struct termio term,term_initial;

RETSIGTYPE (*interrupt_handler) (void);
RETSIGTYPE interrupt_service PROTO((void));
void interrupt_register PROTO((void));
void term_restore PROTO((void));

RETSIGTYPE fatal_handler PROTO((void));
void fatal_handler_register PROTO((void));
extern jmp_buf jmpbuf;
extern int error_count;

/*
 * Registers interrupt handler.
 */
void
interrupt_register ()
{
  interrupt_handler = interrupt_service;
  handle_fd = fileno (stdin);
  ioctl (handle_fd, TCGETA, &term);
  term_initial = term;
  term.c_cc[0] = 0x14;		/* DC4 */
  term.c_cc[5] = 0x12;		/* DC2 */
  term.c_lflag = OFF(term.c_lflag, LNEW_CTLECH); /* dalsi flag ktory ma pre nas vyznam je : term.c_lflag=ON(term.c_lflag,NOFLSH);*/ 
  ioctl (handle_fd, TCSETA, &term);
  sigset (SIGINT, interrupt_handler);
}

/* \verbatim */ 


/* \verbatim{sig_svr3_c_interrupt_service.tex} */

/*
 * Asynchronous interrupt handler.
 */
void
interrupt_service ()
{
#ifdef DEBUG_INTER 
  printfx ("interrupt\n");
#endif
  if ((clif_interrupt_level > 0) || (!virtual_machine_suspended))

/* 
 * Test of the virtual machine running and the level of interrupt.
 * Interrupt is only accepted if the virtual machine is running.
 */

    {
#ifdef DEBUG_INTER 
      printfx ("virtual machine is running, interrupt accepted\n");
#endif
      handler = 1;
    }
  return;
}

/* \verbatim */

/* \verbatim{sig_svr3_c_interrupt_service_sync.tex} */

/*
 * Synchronous interrupt service.
 */
void
interrupt_service_sync ()
{
  handler = 1;
}

/* \verbatim */


/* \verbatim{sig_svr3_c_term_restore.tex} */

/*
 * Restores setting of the terminal at the termination of Clif session.
 */
void
term_restore ()
{
  ioctl (handle_fd, TCSETA, &term_initial);
}

/* \verbatim */

RETSIGTYPE
fatal_handler ()
{
  if (error_count)
    longjmp (jmpbuf, 1);

  sigset (SIGFPE, SIG_DFL);
  sigset (SIGSEGV, SIG_DFL);
}

void
fatal_handler_register ()
{
  if (sigset (SIGFPE, fatal_handler) < 0)
    error_message (4004);
  if (sigset (SIGSEGV, fatal_handler) < 0)
    error_message (4004);
}
