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

version 1.34, 2008/11/01 22:19:30 version 1.43, 2012/04/06 16:34:07
Line 1 Line 1
 /* direct key io driver  /* direct key io driver
   
   Copyright (C) 1995,1996,1997,1998,1999,2002,2003,2006,2007,2008 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.
   
Line 39 Line 39
 typedef unsigned int uint32_t;  typedef unsigned int uint32_t;
 #endif  #endif
   
   #include <stdlib.h>
 #include <stdio.h>  #include <stdio.h>
 #include <signal.h>  #include <signal.h>
 #include <string.h>  #include <string.h>
Line 54  typedef unsigned int uint32_t; Line 55  typedef unsigned int uint32_t;
 #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 446  void deprep_terminal () Line 448  void deprep_terminal ()
 #define VTIME VEOL  #define VTIME VEOL
 #endif  #endif
   
 #include <locale.h>  
   
 void prep_terminal ()  void prep_terminal ()
 {  {
   int tty = fileno (stdin);    int tty = fileno (stdin);
Line 473  void prep_terminal () Line 473  void prep_terminal ()
     return;      /* added by MdG */      return;      /* added by MdG */
   }      /* added by MdG */    }      /* added by MdG */
         
   setlocale(LC_ALL, "");  
   setlocale(LC_NUMERIC, "C");  
   
   /* 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 617  void deprep_terminal () Line 614  void deprep_terminal ()
 }  }
 #endif  /* NEW_TTY_DRIVER */  #endif  /* NEW_TTY_DRIVER */
   
 long key_avail (FILE * stream)  /* an ungetc() variant where we can know that there is a character waiting:
      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
   
      Implementation: just an array containing all the FILEs with ungotten chars.
      Sequential search for membership checking (there should not be many elements)
   */
   
   static FILE **ungotten_files = NULL;
   static size_t n_ungotten = 0; /* actual number */
   static size_t max_ungotten = 0; /* buffer size */
   
   int gf_ungetc(int c, FILE *stream)
   /* 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);
   }
   
   static long search_ungotten(FILE *stream)
   {
     long i;
     for (i=0; i<n_ungotten; i++)
       if (ungotten_files[i] == stream)
         return i;
     return -1;
   }
   
   void gf_regetc(FILE *stream)
   /* remove STREAM from ungotten_files */
   {
     long i = search_ungotten(stream);
     if (i>=0)
       ungotten_files[i] = ungotten_files[--n_ungotten];
   }
   
   int gf_ungottenc(FILE *stream)
   /* true if stream has been ungotten */
   {
     return search_ungotten(stream)>=0;
   }
   
   long key_avail (FILE *stream)
 {  {
   int tty = fileno (stream);    int tty = fileno (stream);
   fd_set selin;    struct pollfd fds = { tty, POLLIN, 0 };
   static struct timeval now = { 0 , 0 };    int chars_avail;
   
     if (gf_ungottenc(stream))
       return 1;
   setvbuf(stream, NULL, _IONBF, 0);    setvbuf(stream, NULL, _IONBF, 0);
   if(!terminal_prepped && stream == stdin)    if(!terminal_prepped && stream == stdin)
     prep_terminal();      prep_terminal();
   
   FD_ZERO(&selin);  #if defined(FIONREAD) && !defined(_WIN32)
   FD_SET(tty, &selin);    if(isatty (tty)) {
   return select(1, &selin, NULL, NULL, &now);      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 644  Cell getkey(FILE * stream) Line 703  Cell getkey(FILE * stream)
   Cell result;    Cell result;
   unsigned char c;    unsigned char c;
   
   setvbuf(stream, NULL, _IONBF, 0);    if (!gf_ungottenc(stream))
       setvbuf(stream, NULL, _IONBF, 0);
   if(!terminal_prepped && stream == stdin)    if(!terminal_prepped && stream == stdin)
     prep_terminal();      prep_terminal();
   
   result = fread(&c, sizeof(c), 1, stream);    result = fread(&c, sizeof(c), 1, stream);
     if (result>0)
       gf_regetc(stream);
   return result==0 ? (errno == EINTR ? 12 : 4) : c;    return result==0 ? (errno == EINTR ? 12 : 4) : c;
 }  }
   

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


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