[project @ 2000-04-14 16:19:43 by rrt]
[ghc-hetmet.git] / ghc / lib / std / cbits / setBuffering.c
index b8cf413..26bfd24 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
  *
- * $Id: setBuffering.c,v 1.1 1998/04/10 10:54:51 simonm Exp $
+ * $Id: setBuffering.c,v 1.8 2000/04/14 16:19:43 rrt Exp $
  *
  * hSetBuffering Runtime Support
  */
 #define SB_BB (-2)
 
 StgInt
-setBuffering(StgAddr fp, StgInt size)
+setBuffering(StgForeignPtr ptr, StgInt size)
 {
-    int flags;
-    int input;
+    IOFileObject* fo = (IOFileObject*)ptr;
+    int flags, rc=0;
+    int input, isaterm;
     struct termios tio;
+    struct stat sb;
+   
 
-    while ((flags = fcntl(fileno((FILE *) fp), F_GETFL)) < 0) {
+    /* First off, flush old buffer.. */
+    if ( (fo->flags & FILEOBJ_WRITE) ) {
+       rc = flushBuffer(ptr);
+    }
+    if (rc<0) return rc;
+
+    /* Let go of old buffer, and reset buffer pointers. */
+    if ( fo->buf != NULL ) {
+       free(fo->buf);
+       fo->bufWPtr = 0;
+       fo->bufRPtr = 0;
+       fo->bufSize = 0;
+       fo->buf     = NULL;
+    }
+
+#ifndef mingw32_TARGET_OS
+    while ((flags = fcntl(fo->fd, F_GETFL)) < 0) {
        if (errno != EINTR) {
            cvtErrno();
            stdErrno();
@@ -46,75 +65,88 @@ setBuffering(StgAddr fp, StgInt size)
     flags &= O_ACCMODE;
     input = flags == O_RDONLY || flags == O_RDWR;
 
+    isaterm = input && isatty(fo->fd);
+#endif
+
     switch (size) {
     case SB_NB:
-       if (setvbuf((FILE *) fp, NULL, _IONBF, 0L) != 0) {
-           cvtErrno();
-           stdErrno();
-           return -1;
-       }
-       if (input && isatty(fileno((FILE *) fp))) {
-
-           /*
-            * Try to switch to CBREAK mode, or whatever they call it these days.
-            */
+        fo->flags &= ~FILEOBJ_LB & ~FILEOBJ_BB;
 
-           if (tcgetattr(fileno((FILE *) fp), &tio) < 0) {
+#ifndef mingw32_TARGET_OS
+       if (isaterm) {
+           /* Switch over to canonical mode. */
+           if (tcgetattr(fo->fd, &tio) < 0) {
                cvtErrno();
                stdErrno();
                return -1;
            }
-           tio.c_lflag &= ~ICANON;
+           tio.c_lflag &=  ~ICANON;
            tio.c_cc[VMIN] = 1;
            tio.c_cc[VTIME] = 0;
-           if (tcsetattr(fileno((FILE *) fp), TCSANOW, &tio) < 0) {
+           if (tcsetattr(fo->fd, TCSANOW, &tio) < 0) {
                cvtErrno();
                stdErrno();
                return -1;
            }
        }
+#endif
        return 0;
-       break;
     case SB_LB:
-       if (setvbuf((FILE *) fp, NULL, _IOLBF, BUFSIZ) != 0) {
-           cvtErrno();
-           stdErrno();
-           return -1;
-       }
+        fo->flags &= ~FILEOBJ_BB;
+       fo->flags |= FILEOBJ_LB;
+        size = BUFSIZ;
        break;
     case SB_BB:
 
-       /*
-        * We should actually peek at the buffer size in the stat struct, if there
-        * is one.  Something to occupy us later, when we're bored.
-        */
+#ifdef HAVE_ST_BLKSIZE
+       while (fstat(fo->fd, &sb) < 0) {
+          /* not very likely.. */
+          if ( errno != EINTR ) {
+             cvtErrno();
+             stdErrno();
+             return -1;
+          }
+        }
+       size = sb.st_blksize;
+#else
        size = BUFSIZ;
+#endif
+        fo->flags &= ~FILEOBJ_LB;
+       fo->flags |= FILEOBJ_BB;
        /* fall through */
     default:
-       if (setvbuf((FILE *) fp, NULL, _IOFBF, size) != 0) {
-           cvtErrno();
-           stdErrno();
-           return -1;
-       }
        break;
     }
-    if (input && isatty(fileno((FILE *) fp))) {
+  
+    if ( size > 0) {
+       fo->buf = malloc(size*sizeof(char));
+       if (fo->buf == NULL) {
+           return -1;
+       }  
+    }
+    fo->bufSize = size;
+#ifndef mingw32_TARGET_OS
+    if (isaterm) {
 
        /*
         * Try to switch back to cooked mode.
         */
 
-       if (tcgetattr(fileno((FILE *) fp), &tio) < 0) {
+       if (tcgetattr(fo->fd, &tio) < 0) {
            cvtErrno();
            stdErrno();
            return -1;
        }
        tio.c_lflag |= ICANON;
-       if (tcsetattr(fileno((FILE *) fp), TCSANOW, &tio) < 0) {
+       if (tcsetattr(fo->fd, TCSANOW, &tio) < 0) {
            cvtErrno();
            stdErrno();
            return -1;
        }
     }
+#endif
     return 0;
 }
+
+StgInt const_BUFSIZ() { return BUFSIZ; }
+