version 1.4, 1994/07/08 15:00:45
|
version 1.18, 1996/10/06 22:24:17
|
Line 1
|
Line 1
|
/* direct key io driver |
/* direct key io driver; signal handler |
|
|
The following is stolen from the readline library for bash |
Copyright (C) 1995 Free Software Foundation, Inc. |
|
|
|
This file is part of Gforth. |
|
|
|
Gforth 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. |
|
|
|
The following is stolen from the readline library for bash |
*/ |
*/ |
|
|
/* Use -DDOMAINOS for Apollo Domain-OS. |
/* |
Use -D_POSIX_VERSION for POSIX systems. |
Use -D_POSIX_VERSION for POSIX systems. |
*/ |
*/ |
|
|
#ifdef DOMAINOS |
#include "config.h" |
|
#include <unistd.h> |
|
|
|
#ifdef apollo |
#define _POSIX_VERSION |
#define _POSIX_VERSION |
#endif |
#endif |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <signal.h> |
#include <signal.h> |
|
#include <string.h> |
#include <sys/types.h> |
#include <sys/types.h> |
#ifndef DOMAINOS |
#if !defined(apollo) && !defined(MSDOS) |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
#endif |
#endif |
#include <fcntl.h> |
#include <fcntl.h> |
Line 23
|
Line 45
|
#include "forth.h" |
#include "forth.h" |
#include "io.h" |
#include "io.h" |
|
|
|
#ifndef MSDOS |
#if defined (__GNUC__) |
#if defined (__GNUC__) |
# define alloca __builtin_alloca |
# define alloca __builtin_alloca |
#else |
#else |
Line 31
|
Line 54
|
# endif |
# endif |
#endif |
#endif |
|
|
#if defined (HAVE_UNISTD_H) |
|
# include <unistd.h> |
|
#endif |
|
|
|
#define NEW_TTY_DRIVER |
#define NEW_TTY_DRIVER |
#define HAVE_BSD_SIGNALS |
#define HAVE_BSD_SIGNALS |
#ifndef DOMAINOS |
/* |
|
#ifndef apollo |
#define USE_XON_XOFF |
#define USE_XON_XOFF |
#endif |
#endif |
|
*/ |
|
|
|
#define HANDLE_SIGNALS |
|
|
/* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */ |
/* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */ |
#if defined (USG) && !defined (hpux) |
#if defined (USG) && !defined (hpux) |
Line 48
|
Line 71
|
|
|
/* System V machines use termio. */ |
/* System V machines use termio. */ |
#if !defined (_POSIX_VERSION) |
#if !defined (_POSIX_VERSION) |
# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) |
# if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) || defined (Solaris) || defined(_WIN32) |
# undef NEW_TTY_DRIVER |
# undef NEW_TTY_DRIVER |
# define TERMIO_TTY_DRIVER |
# define TERMIO_TTY_DRIVER |
# include <termio.h> |
# include <termio.h> |
Line 89
|
Line 112
|
#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ |
#endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ |
|
|
#include <errno.h> |
#include <errno.h> |
extern int errno; |
/* extern int errno; */ |
|
|
#if defined (SHELL) |
#if defined (SHELL) |
# include <posixstat.h> |
# include <posixstat.h> |
Line 104 extern int errno;
|
Line 127 extern int errno;
|
# endif /* USGr3 */ |
# endif /* USGr3 */ |
#endif /* USG && hpux */ |
#endif /* USG && hpux */ |
|
|
#if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(DOMAINOS) |
#if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(apollo) |
# include <dirent.h> |
# include <dirent.h> |
# define direct dirent |
# define direct dirent |
# if defined (_POSIX_VERSION) |
# if defined (_POSIX_VERSION) |
Line 161 static int eof_char = CTRL ('D');
|
Line 184 static int eof_char = CTRL ('D');
|
/* **************************************************************** */ |
/* **************************************************************** */ |
|
|
/* Non-zero means that the terminal is in a prepped state. */ |
/* Non-zero means that the terminal is in a prepped state. */ |
static int terminal_prepped = 0; |
int terminal_prepped = 0; |
|
|
#if defined (NEW_TTY_DRIVER) |
#if defined (NEW_TTY_DRIVER) |
|
|
Line 261 void prep_terminal ()
|
Line 284 void prep_terminal ()
|
if (terminal_prepped) |
if (terminal_prepped) |
return; |
return; |
|
|
|
if (!isatty(tty)) { /* added by MdG */ |
|
terminal_prepped = 1; /* added by MdG */ |
|
return; /* added by MdG */ |
|
} /* added by MdG */ |
|
|
oldmask = sigblock (sigmask (SIGINT)); |
oldmask = sigblock (sigmask (SIGINT)); |
|
|
/* We always get the latest tty values. Maybe stty changed them. */ |
/* We always get the latest tty values. Maybe stty changed them. */ |
Line 367 void deprep_terminal ()
|
Line 395 void deprep_terminal ()
|
if (!terminal_prepped) |
if (!terminal_prepped) |
return; |
return; |
|
|
|
/* Added by MdG */ |
|
if (!isatty(tty)) { |
|
terminal_prepped = 0; |
|
return; |
|
} |
|
|
oldmask = sigblock (sigmask (SIGINT)); |
oldmask = sigblock (sigmask (SIGINT)); |
|
|
the_ttybuff.sg_flags = original_tty_flags; |
the_ttybuff.sg_flags = original_tty_flags; |
Line 421 void prep_terminal ()
|
Line 455 void prep_terminal ()
|
if (terminal_prepped) |
if (terminal_prepped) |
return; |
return; |
|
|
|
if (!isatty(tty)) { /* added by MdG */ |
|
terminal_prepped = 1; /* added by MdG */ |
|
return; /* added by MdG */ |
|
} /* added by MdG */ |
|
|
/* Try to keep this function from being INTerrupted. We can do it |
/* Try to keep this function from being INTerrupted. We can do it |
on POSIX and systems with BSD-like signal handling. */ |
on POSIX and systems with BSD-like signal handling. */ |
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
Line 525 void deprep_terminal ()
|
Line 564 void deprep_terminal ()
|
if (!terminal_prepped) |
if (!terminal_prepped) |
return; |
return; |
|
|
|
/* Added by MdG */ |
|
if (!isatty(tty)) { |
|
terminal_prepped = 0; |
|
return; |
|
} |
|
|
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
sigemptyset (&set); |
sigemptyset (&set); |
sigemptyset (&oset); |
sigemptyset (&oset); |
Line 568 long key_avail (stream)
|
Line 613 long key_avail (stream)
|
long chars_avail = pending; |
long chars_avail = pending; |
int result; |
int result; |
|
|
|
if(!terminal_prepped) prep_terminal(); |
|
|
#if defined (FIONREAD) |
#if defined (FIONREAD) |
result = ioctl (tty, FIONREAD, &chars_avail); |
result = ioctl (tty, FIONREAD, &chars_avail); |
#endif |
#endif |
Line 603 unsigned char getkey(stream)
|
Line 650 unsigned char getkey(stream)
|
int result; |
int result; |
unsigned char c; |
unsigned char c; |
|
|
|
if(!terminal_prepped) prep_terminal(); |
|
|
while (pending < 0) |
while (pending < 0) |
{ |
{ |
result = read (fileno (stream), &c, sizeof (char)); |
result = read (fileno (stream), &c, sizeof (char)); |
Line 613 unsigned char getkey(stream)
|
Line 662 unsigned char getkey(stream)
|
/* If zero characters are returned, then the file that we are |
/* If zero characters are returned, then the file that we are |
reading from is empty! Return EOF in that case. */ |
reading from is empty! Return EOF in that case. */ |
if (result == 0) |
if (result == 0) |
return (0); |
return CTRL('D'); |
|
|
/* If the error that we received was SIGINT, then try again, |
/* If the error that we received was SIGINT, then try again, |
this is simply an interrupted system call to read (). |
this is simply an interrupted system call to read (). |
Line 667 int main()
|
Line 716 int main()
|
puts(""); |
puts(""); |
} |
} |
#endif |
#endif |
|
#endif /* MSDOS */ |
|
|
/* signal handling taken from pfe by Dirk Zoller (Copylefted) - anton */ |
/* signal handling adapted from pfe by Dirk Zoller (Copylefted) - anton */ |
/* !! needs cleanup */ |
|
char * |
|
sigmsg (int sig) |
|
{ |
|
static char buf [25]; |
|
static char *msg [] = |
|
{ |
|
"Hangup", /* These strings are cited from */ |
|
"Interrupt", /* Rochkind: Advanced UNIX programming */ |
|
"Quit", |
|
"Illegal Instruction", |
|
"Trace Trap", |
|
"IOT instruction", |
|
"EMT instruction", |
|
"Floating point exception", |
|
"Kill", |
|
"Bus error", |
|
"Segmentation Violation", |
|
"Bad arg to system call", |
|
"Broken pipe", |
|
"Alarm clock", |
|
"Terminate signal", |
|
"User signal 1", |
|
"User signal 2", |
|
}; |
|
|
|
if ((unsigned)sig <= 17) |
|
return msg [sig - 1]; |
|
sprintf (buf, "signal %d received", sig); |
|
return buf; |
|
} |
|
|
|
static void |
static void |
graceful_exit (int sig) |
graceful_exit (int sig) |
{ |
{ |
deprep_terminal(); |
deprep_terminal(); |
if ((unsigned)sig <= 17) |
fprintf (stderr, "\n\n%s.\n", strsignal (sig)); |
fprintf (stderr, "\n\n%s.\n", sigmsg (sig)); |
|
else |
|
fprintf (stderr, "\n\nSignal %d received, terminated.\n", sig); |
|
exit (0x80|sig); |
exit (0x80|sig); |
} |
} |
|
|
Line 717 jmp_buf throw_jmp_buf;
|
Line 733 jmp_buf throw_jmp_buf;
|
static void |
static void |
signal_throw(int sig) |
signal_throw(int sig) |
{ |
{ |
static int throw_codes[] = { |
int code; |
-256, |
struct { |
-28, |
int signal; |
-257, |
int throwcode; |
-258, |
} *p, throwtable[] = { |
-259, |
{ SIGINT, -28 }, |
-260, |
{ SIGFPE, -55 }, |
-261, |
#ifdef SIGBUS |
-55, |
{ SIGBUS, -23 }, |
-262, |
#endif |
-23, |
{ SIGSEGV, -9 }, |
-9, |
|
-263, |
|
-264, |
|
-265, |
|
-266, |
|
-267, |
|
-268, |
|
}; |
}; |
signal(sig,signal_throw); |
signal(sig,signal_throw); |
longjmp(throw_jmp_buf,throw_codes[sig-1]); /* or use siglongjmp ? */ |
for (code=-256-sig, p=throwtable; p<throwtable+(sizeof(throwtable)/sizeof(*p)); p++) |
|
if (sig == p->signal) { |
|
code = p->throwcode; |
|
break; |
|
} |
|
longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ |
|
} |
|
|
|
UCell cols=80; |
|
#if defined(MSDOS) || defined (_WIN32) |
|
UCell rows=25; |
|
#else |
|
UCell rows=24; |
|
#endif |
|
|
|
#ifdef SIGCONT |
|
static void termprep (int sig) |
|
{ |
|
signal(sig,termprep); |
|
terminal_prepped=0; |
|
} |
|
#endif |
|
|
|
#ifdef SIGWINCH |
|
void get_winsize() |
|
{ |
|
#ifdef TIOCGWINSZ |
|
struct winsize size; |
|
|
|
if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) { |
|
rows = size.ws_row; |
|
cols = size.ws_col; |
|
} |
|
#else |
|
char *s, *ends; |
|
unsigned long ul; |
|
if (s=getenv("LINES")) { |
|
rows=atoi(s); |
|
if (rows==0) |
|
rows=24; |
|
} |
|
if (s=getenv("COLUMNS")) { |
|
rows=atoi(s); |
|
if (rows==0) |
|
cols=80; |
|
} |
|
#endif |
|
} |
|
|
|
static void change_winsize(int sig) |
|
{ |
|
signal(sig,change_winsize); |
|
#ifdef TIOCGWINSZ |
|
get_winsize(); |
|
#endif |
} |
} |
|
#endif |
|
|
void |
void install_signal_handlers (void) |
install_signal_handlers (void) |
|
{ |
{ |
/* !! These definitions seem to be system dependent |
|
We could have them in the machine.h file, |
#if 0 |
but I would like something more automatic - anton */ |
/* these signals are handled right by default, no need to handle them; |
#define SIGS_TO_IGNORE SIGCHLD |
they are listed here just for fun */ |
#define SIGS_TO_ABORT SIGINT, SIGILL, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, \ |
static short sigs_to_default [] = { |
SIGALRM, SIGBUS |
#ifdef SIGCHLD |
#define SIGS_TO_QUIT SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, \ |
SIGCHLD, |
SIGTERM |
#endif |
|
#ifdef SIGINFO |
static short sigs_to_ignore [] = { SIGS_TO_IGNORE }; |
SIGINFO, |
static short sigs_to_abort [] = { SIGS_TO_ABORT }; |
#endif |
static short sigs_to_quit [] = { SIGS_TO_QUIT }; |
#ifdef SIGIO |
|
SIGIO, |
|
#endif |
|
#ifdef SIGLOST |
|
SIGLOST, |
|
#endif |
|
#ifdef SIGKILL |
|
SIGKILL, |
|
#endif |
|
#ifdef SIGSTOP |
|
SIGSTOP, |
|
#endif |
|
#ifdef SIGPWR |
|
SIGPWR, |
|
#endif |
|
#ifdef SIGMSG |
|
SIGMSG, |
|
#endif |
|
#ifdef SIGDANGER |
|
SIGDANGER, |
|
#endif |
|
#ifdef SIGMIGRATE |
|
SIGMIGRATE, |
|
#endif |
|
#ifdef SIGPRE |
|
SIGPRE, |
|
#endif |
|
#ifdef SIGVIRT |
|
SIGVIRT, |
|
#endif |
|
#ifdef SIGGRANT |
|
SIGGRANT, |
|
#endif |
|
#ifdef SIGRETRACT |
|
SIGRETRACT, |
|
#endif |
|
#ifdef SIGSOUND |
|
SIGSOUND, |
|
#endif |
|
#ifdef SIGSAK |
|
SIGSAK, |
|
#endif |
|
#ifdef SIGTSTP |
|
SIGTSTP, |
|
#endif |
|
#ifdef SIGTTIN |
|
SIGTTIN, |
|
#endif |
|
#ifdef SIGTTOU |
|
SIGTTOU, |
|
#endif |
|
#ifdef SIGSTKFLT |
|
SIGSTKFLT, |
|
#endif |
|
#ifdef SIGUNUSED |
|
SIGUNUSED, |
|
#endif |
|
}; |
|
#endif |
|
|
|
static short sigs_to_throw [] = { |
|
#ifdef SIGBREAK |
|
SIGBREAK, |
|
#endif |
|
#ifdef SIGINT |
|
SIGINT, |
|
#endif |
|
#ifdef SIGILL |
|
SIGILL, |
|
#endif |
|
#ifdef SIGEMT |
|
SIGEMT, |
|
#endif |
|
#ifdef SIGFPE |
|
SIGFPE, |
|
#endif |
|
#ifdef SIGIOT |
|
SIGIOT, |
|
#endif |
|
#ifdef SIGSEGV |
|
SIGSEGV, |
|
#endif |
|
#ifdef SIGALRM |
|
SIGALRM, |
|
#endif |
|
#ifdef SIGPIPE |
|
SIGPIPE, |
|
#endif |
|
#ifdef SIGPOLL |
|
SIGPOLL, |
|
#endif |
|
#ifdef SIGPROF |
|
SIGPROF, |
|
#endif |
|
#ifdef SIGBUS |
|
SIGBUS, |
|
#endif |
|
#ifdef SIGSYS |
|
SIGSYS, |
|
#endif |
|
#ifdef SIGTRAP |
|
SIGTRAP, |
|
#endif |
|
#ifdef SIGURG |
|
SIGURG, |
|
#endif |
|
#ifdef SIGUSR1 |
|
SIGUSR1, |
|
#endif |
|
#ifdef SIGUSR2 |
|
SIGUSR2, |
|
#endif |
|
#ifdef SIGVTALRM |
|
SIGVTALRM, |
|
#endif |
|
#ifdef SIGXFSZ |
|
SIGXFSZ, |
|
#endif |
|
}; |
|
static short sigs_to_quit [] = { |
|
#ifdef SIGHUP |
|
SIGHUP, |
|
#endif |
|
#ifdef SIGQUIT |
|
SIGQUIT, |
|
#endif |
|
#ifdef SIGABRT |
|
SIGABRT, |
|
#endif |
|
#ifdef SIGTERM |
|
SIGTERM, |
|
#endif |
|
#ifdef SIGXCPU |
|
SIGXCPU, |
|
#endif |
|
}; |
int i; |
int i; |
|
|
#define DIM(X) (sizeof (X) / sizeof *(X)) |
#define DIM(X) (sizeof (X) / sizeof *(X)) |
|
/* |
for (i = 0; i < DIM (sigs_to_ignore); i++) |
for (i = 0; i < DIM (sigs_to_ignore); i++) |
if (sigs_to_ignore [i]) |
signal (sigs_to_ignore [i], SIG_IGN); |
signal (sigs_to_ignore [i], SIG_IGN); |
*/ |
for (i = 0; i < DIM (sigs_to_abort); i++) |
for (i = 0; i < DIM (sigs_to_throw); i++) |
signal (sigs_to_abort [i], signal_throw); /* !! change to throw */ |
signal (sigs_to_throw [i], signal_throw); |
for (i = 0; i < DIM (sigs_to_quit); i++) |
for (i = 0; i < DIM (sigs_to_quit); i++) |
signal (sigs_to_quit [i], graceful_exit); |
signal (sigs_to_quit [i], graceful_exit); |
|
#ifdef SIGCONT |
|
signal (SIGCONT, termprep); |
|
#endif |
|
#ifdef SIGWINCH |
|
signal (SIGWINCH, change_winsize); |
|
#endif |
} |
} |
/* end signal handling */ |
/* end signal handling */ |