Diff for /gforth/engine/io.c between versions 1.5 and 1.43

version 1.5, 1998/05/02 21:29:02 version 1.43, 2012/04/06 16:34:07
Line 1 Line 1
 /* direct key io driver; signal handler  /* direct key io driver
   
   Copyright (C) 1995 Free Software Foundation, Inc.    Copyright (C) 1995,1996,1997,1998,1999,2002,2003,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
   
   This file is part of Gforth.    This file is part of Gforth.
   
   Gforth is free software; you can redistribute it and/or    Gforth is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License    modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2    as published by the Free Software Foundation, either version 3
   of the License, or (at your option) any later version.    of the License, or (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,    This program is distributed in the hope that it will be useful,
Line 15 Line 15
   GNU General Public License for more details.    GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License    You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software    along with this program; if not, see http://www.gnu.org/licenses/.
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
   
   The following is stolen from the readline library for bash    The following is stolen from the readline library for bash
 */  */
Line 26 Line 25
 */  */
   
 #include "config.h"  #include "config.h"
   #include "forth.h"
   #include <sys/time.h>
   #include <sys/types.h>
 #include <unistd.h>  #include <unistd.h>
   
 #if defined(apollo) || defined(_WIN32)  #if defined(apollo) || defined(_WIN32)
 #define _POSIX_VERSION  #define _POSIX_VERSION
 #endif  #endif
   
   #if !defined(Solaris) && defined(sun) && defined(__svr4__)
   #define Solaris
   typedef unsigned int uint32_t;
   #endif
   
   #include <stdlib.h>
 #include <stdio.h>  #include <stdio.h>
 #include <signal.h>  #include <signal.h>
 #include <string.h>  #include <string.h>
 #include <sys/types.h>  
 #if !defined(apollo) && !defined(MSDOS)  #if !defined(apollo) && !defined(MSDOS)
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
 #endif  #endif
Line 45 Line 52
 #include <sys/filio.h>  #include <sys/filio.h>
 #endif  #endif
 #include <setjmp.h>  #include <setjmp.h>
 #include "forth.h"  
 #include "io.h"  #include "io.h"
   
 #ifndef MSDOS  #ifndef MSDOS
   #include <poll.h>
 #if defined (__GNUC__)  #if defined (__GNUC__)
 #  define alloca __builtin_alloca  #  define alloca __builtin_alloca
 #else  #else
Line 607  void deprep_terminal () Line 614  void deprep_terminal ()
 }  }
 #endif  /* NEW_TTY_DRIVER */  #endif  /* NEW_TTY_DRIVER */
   
 /* If a character is available to be read, then read it  /* an ungetc() variant where we can know that there is a character waiting:
    and stuff it into IBUFFER.  Otherwise, just return. */     gf_ungetc: like ungetc
      gf_regetc: call when reading a char, but does not get the character
      gf_ungottenc: true if there is a char waiting
   
 long pending = -1L;     Implementation: just an array containing all the FILEs with ungotten chars.
      Sequential search for membership checking (there should not be many elements)
   */
   
 long key_avail (stream)  static FILE **ungotten_files = NULL;
         FILE *stream;  static size_t n_ungotten = 0; /* actual number */
 {  static size_t max_ungotten = 0; /* buffer size */
   int tty = fileno (stream);  
   int chars_avail = pending;  int gf_ungetc(int c, FILE *stream)
   int result;  /* like ungetc, but works with the others */
   {
     if (n_ungotten>=max_ungotten) {
       max_ungotten = max_ungotten*2+1;
       ungotten_files = realloc(ungotten_files, max_ungotten*sizeof(FILE *));
     }
     ungotten_files[n_ungotten++] = stream;
     return ungetc(c, stream);
   }
   
   if(!terminal_prepped)  prep_terminal();  static long search_ungotten(FILE *stream)
   {
     long i;
     for (i=0; i<n_ungotten; i++)
       if (ungotten_files[i] == stream)
         return i;
     return -1;
   }
   
 #ifndef _WIN32  void gf_regetc(FILE *stream)
   result = ioctl (tty, FIONREAD, &chars_avail);  /* remove STREAM from ungotten_files */
 #else  {
   {    long i = search_ungotten(stream);
      fd_set selin;    if (i>=0)
      static int now[2] = { 0 , 0 };      ungotten_files[i] = ungotten_files[--n_ungotten];
      int res;  }
   
      FD_ZERO(&selin);  
      FD_SET(tty, &selin);  
      chars_avail=select(1, &selin, NULL, NULL, now);  
   }  
 #endif  
   
   if(chars_avail == -1L)  int gf_ungottenc(FILE *stream)
     {  unsigned char inchar;  /* true if stream has been ungotten */
   {
     return search_ungotten(stream)>=0;
   }
   
        fcntl(tty, F_SETFL, O_NDELAY);  long key_avail (FILE *stream)
        result = read(tty, &inchar, sizeof(char));  {
        if(result == sizeof(char))    int tty = fileno (stream);
        {    struct pollfd fds = { tty, POLLIN, 0 };
          chars_avail = 1;    int chars_avail;
          pending = (long)inchar;  
        }  
        else  
          chars_avail = 0;  
        fcntl(tty, F_SETFL, 0);  
     }  
   
   return chars_avail;    if (gf_ungottenc(stream))
       return 1;
     setvbuf(stream, NULL, _IONBF, 0);
     if(!terminal_prepped && stream == stdin)
       prep_terminal();
   
   #if defined(FIONREAD) && !defined(_WIN32)
     if(isatty (tty)) {
       int result = ioctl (tty, FIONREAD, &chars_avail);
     } else
   #endif
     {
       chars_avail = poll(&fds, 1, 0);
     }
     if (chars_avail > 0) {
       /* getc won't block */
       int c = getc(stream);
       if (c==EOF)
         return 0;
       gf_ungetc(c, stream);
     }
     return (chars_avail == -1) ? 0 : chars_avail;
 }  }
   
 /* Get a key from the buffer of characters to be read.  /* Get a key from the buffer of characters to be read.
Line 660  long key_avail (stream) Line 698  long key_avail (stream)
 /* When compiling and running in the `Posix' environment, Ultrix does  /* When compiling and running in the `Posix' environment, Ultrix does
    not restart system calls, so this needs to do it. */     not restart system calls, so this needs to do it. */
   
 unsigned char getkey(stream)  Cell getkey(FILE * stream)
      FILE *stream;  
 {  {
   int result;    Cell result;
   unsigned char c;    unsigned char c;
   
   if(!terminal_prepped)  prep_terminal();    if (!gf_ungottenc(stream))
       setvbuf(stream, NULL, _IONBF, 0);
   while (pending < 0)    if(!terminal_prepped && stream == stdin)
     {      prep_terminal();
       result = read (fileno (stream), &c, sizeof (char));  
   
       if (result == sizeof (char))    result = fread(&c, sizeof(c), 1, stream);
         return /* (c == 0x7F ? 0x08 :*/ c /*)*/;    if (result>0)
       gf_regetc(stream);
       /* If zero characters are returned, then the file that we are    return result==0 ? (errno == EINTR ? 12 : 4) : c;
          reading from is empty!  Return EOF in that case. */  }
       if (result == 0)  
         return CTRL('D');  
   
       /* If the error that we received was SIGINT, then try again,  
          this is simply an interrupted system call to read ().  
          Otherwise, some error ocurred, also signifying EOF. */  
       if (errno != EINTR)  
         return (EOF);  
     }  
   
   result = (int) pending;  #ifdef STANDALONE
   pending = -1L;  void emit_char(char x)
   {
     putc(x, stdout);
   }
   
   return result;  void type_chars(char *addr, unsigned int l)
   {
     fwrite(addr, l, 1, stdout);
 }  }
   #endif
   
 #ifdef TEST  #ifdef TEST
   
Line 734  int main() Line 767  int main()
 #endif  #endif
 #endif /* MSDOS */  #endif /* MSDOS */
   
 /* signal handling adapted from pfe by Dirk Zoller (Copylefted) - anton */  
   
 static void  
 graceful_exit (int sig)  
 {  
   deprep_terminal();  
   fprintf (stderr, "\n\n%s.\n", strsignal (sig));  
   exit (0x80|sig);  
 }  
   
 jmp_buf throw_jmp_buf;  
   
 static void   
 signal_throw(int sig)  
 {  
   int code;  
   struct {  
     int signal;  
     int throwcode;  
   } *p, throwtable[] = {  
     { SIGINT, -28 },  
     { SIGFPE, -55 },  
 #ifdef SIGBUS  
     { SIGBUS, -23 },  
 #endif  
     { SIGSEGV, -9 },  
   };  
   signal(sig,signal_throw);  
   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 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++)  
     signal (sigs_to_ignore [i], SIG_IGN);  
 */  
   for (i = 0; i < DIM (sigs_to_throw); i++)  
     signal (sigs_to_throw [i], die_on_signal ? graceful_exit : signal_throw);  
   for (i = 0; i < DIM (sigs_to_quit); i++)  
     signal (sigs_to_quit [i], graceful_exit);  
 #ifdef SIGCONT  
     signal (SIGCONT, termprep);  
 #endif  
 #ifdef SIGWINCH  
     signal (SIGWINCH, change_winsize);  
 #endif  
 }  
 /* end signal handling */  

Removed from v.1.5  
changed lines
  Added in v.1.43


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>