/*
* (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();
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; }
+