--- gforth/Attic/io.c 1995/03/13 09:17:29 1.8 +++ gforth/Attic/io.c 1996/09/23 20:41:59 1.17 @@ -1,12 +1,31 @@ -/* 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 -D_POSIX_VERSION for POSIX systems. */ +#include "config.h" #include #ifdef apollo @@ -15,8 +34,9 @@ #include #include +#include #include -#ifndef apollo +#if !defined(apollo) && !defined(MSDOS) #include #endif #include @@ -25,6 +45,7 @@ #include "forth.h" #include "io.h" +#ifndef MSDOS #if defined (__GNUC__) # define alloca __builtin_alloca #else @@ -91,7 +112,7 @@ #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */ #include -extern int errno; +/* extern int errno; */ #if defined (SHELL) # include @@ -163,7 +184,7 @@ static int eof_char = CTRL ('D'); /* **************************************************************** */ /* 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) @@ -263,6 +284,11 @@ void prep_terminal () if (terminal_prepped) return; + if (!isatty(tty)) { /* added by MdG */ + terminal_prepped = 1; /* added by MdG */ + return; /* added by MdG */ + } /* added by MdG */ + oldmask = sigblock (sigmask (SIGINT)); /* We always get the latest tty values. Maybe stty changed them. */ @@ -369,6 +395,12 @@ void deprep_terminal () if (!terminal_prepped) return; +/* Added by MdG */ + if (!isatty(tty)) { + terminal_prepped = 0; + return; + } + oldmask = sigblock (sigmask (SIGINT)); the_ttybuff.sg_flags = original_tty_flags; @@ -423,6 +455,11 @@ void prep_terminal () if (terminal_prepped) 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 on POSIX and systems with BSD-like signal handling. */ #if defined (HAVE_POSIX_SIGNALS) @@ -527,6 +564,12 @@ void deprep_terminal () if (!terminal_prepped) return; +/* Added by MdG */ + if (!isatty(tty)) { + terminal_prepped = 0; + return; + } + #if defined (HAVE_POSIX_SIGNALS) sigemptyset (&set); sigemptyset (&oset); @@ -570,6 +613,8 @@ long key_avail (stream) long chars_avail = pending; int result; + if(!terminal_prepped) prep_terminal(); + #if defined (FIONREAD) result = ioctl (tty, FIONREAD, &chars_avail); #endif @@ -605,6 +650,8 @@ unsigned char getkey(stream) int result; unsigned char c; + if(!terminal_prepped) prep_terminal(); + while (pending < 0) { result = read (fileno (stream), &c, sizeof (char)); @@ -615,7 +662,7 @@ unsigned char getkey(stream) /* If zero characters are returned, then the file that we are reading from is empty! Return EOF in that case. */ if (result == 0) - return (0); + return CTRL('D'); /* If the error that we received was SIGINT, then try again, this is simply an interrupted system call to read (). @@ -669,48 +716,15 @@ int main() puts(""); } #endif +#endif /* MSDOS */ -/* signal handling taken 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; -} +/* signal handling adapted from pfe by Dirk Zoller (Copylefted) - anton */ static void graceful_exit (int sig) { deprep_terminal(); - if ((unsigned)sig <= 17) - fprintf (stderr, "\n\n%s.\n", sigmsg (sig)); - else - fprintf (stderr, "\n\nSignal %d received, terminated.\n", sig); + fprintf (stderr, "\n\n%s.\n", strsignal (sig)); exit (0x80|sig); } @@ -719,64 +733,242 @@ jmp_buf throw_jmp_buf; static void signal_throw(int sig) { - static int throw_codes[] = { - -256, - -28, - -257, - -258, - -259, - -260, - -261, - -55, - -262, - -23, - -9, - -263, - -264, - -265, - -266, - -267, - -268, + int code; + struct { + int signal; + int throwcode; + } *p, throwtable[] = { + { SIGINT, -28 }, + { SIGFPE, -55 }, +#ifdef SIGBUS + { SIGBUS, -23 }, +#endif + { SIGSEGV, -9 }, }; signal(sig,signal_throw); - longjmp(throw_jmp_buf,throw_codes[sig-1]); /* or use siglongjmp ? */ + for (code=-256-sig, p=throwtable; psignal) { + code = p->throwcode; + break; + } + longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ } -static void -termprep (int sig) +UCell cols=80; +#ifdef MSDOS +UCell rows=25; +#else +UCell rows=24; +#endif + +#ifdef SIGCONT +static void termprep (int sig) { - terminal_prepped=0; prep_terminal(); 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 } -void -install_signal_handlers (void) +static void change_winsize(int sig) { -/* !! These definitions seem to be system dependent - We could have them in the machine.h file, - but I would like something more automatic - anton */ -#define SIGS_TO_IGNORE SIGCHLD -#define SIGS_TO_ABORT SIGINT, SIGILL, SIGFPE, SIGUSR1, SIGSEGV, SIGUSR2, \ - SIGALRM, SIGBUS -#define SIGS_TO_QUIT SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, \ - SIGTERM -#define SIGS_TO_TERMPREP SIGCONT - - static short sigs_to_ignore [] = { SIGS_TO_IGNORE }; - static short sigs_to_abort [] = { SIGS_TO_ABORT }; - static short sigs_to_quit [] = { SIGS_TO_QUIT }; - static short sigs_to_termprep [] = { SIGS_TO_TERMPREP }; + signal(sig,change_winsize); +#ifdef TIOCGWINSZ + get_winsize(); +#endif +} +#endif + +void install_signal_handlers (void) +{ + +#if 0 +/* these signals are handled right by default, no need to handle them; + they are listed here just for fun */ + static short sigs_to_default [] = { +#ifdef SIGCHLD + SIGCHLD, +#endif +#ifdef SIGINFO + SIGINFO, +#endif +#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; #define DIM(X) (sizeof (X) / sizeof *(X)) +/* for (i = 0; i < DIM (sigs_to_ignore); i++) - if (sigs_to_ignore [i]) - signal (sigs_to_ignore [i], SIG_IGN); - for (i = 0; i < DIM (sigs_to_abort); i++) - signal (sigs_to_abort [i], signal_throw); /* !! change to throw */ + signal (sigs_to_ignore [i], SIG_IGN); +*/ + for (i = 0; i < DIM (sigs_to_throw); i++) + signal (sigs_to_throw [i], signal_throw); for (i = 0; i < DIM (sigs_to_quit); i++) signal (sigs_to_quit [i], graceful_exit); - for (i = 0; i < DIM (sigs_to_termprep); i++) - signal (sigs_to_termprep [i], termprep); +#ifdef SIGCONT + signal (SIGCONT, termprep); +#endif +#ifdef SIGWINCH + signal (SIGWINCH, change_winsize); +#endif } /* end signal handling */