ExtStream.st
changeset 612 e640bef6170e
parent 593 19d568779cf7
child 665 429936f8e6e7
--- a/ExtStream.st	Thu Nov 23 02:32:01 1995 +0100
+++ b/ExtStream.st	Thu Nov 23 02:48:32 1995 +0100
@@ -11,17 +11,16 @@
 "
 
 ReadWriteStream subclass:#ExternalStream
-       instanceVariableNames:'filePointer mode buffered binary useCRLF hitEOF didWrite lastErrorNumber'
-       classVariableNames:'Lobby LastErrorNumber
-			   ReadErrorSignal WriteErrorSignal
-			   InvalidReadSignal InvalidWriteSignal InvalidModeSignal
-			   OpenErrorSignal StreamNotOpenSignal'
-       poolDictionaries:''
-       category:'Streams-External'
+	 instanceVariableNames:'filePointer mode buffered binary useCRLF hitEOF didWrite
+                lastErrorNumber'
+	 classVariableNames:'Lobby LastErrorNumber ReadErrorSignal WriteErrorSignal
+                InvalidReadSignal InvalidWriteSignal InvalidModeSignal
+                OpenErrorSignal StreamNotOpenSignal'
+	 poolDictionaries:''
+	 category:'Streams-External'
 !
 
 !ExternalStream primitiveDefinitions!
-
 %{
 #include <stdio.h>
 #define _STDIO_H_INCLUDED_
@@ -82,10 +81,6 @@
 "
 !
 
-version
-    ^ '$Header: /cvs/stx/stx/libbasic/Attic/ExtStream.st,v 1.69 1995-11-22 15:08:34 cg Exp $'
-!
-
 documentation
 "
     ExternalStream defines protocol common to Streams which have a file-descriptor and 
@@ -179,6 +174,10 @@
       Two macros (__READING__ and __WRITING__) have been defined to be used before every
       fread/fgetc and fwrite/putc respectively.
 "
+!
+
+version
+    ^ '$Header: /cvs/stx/stx/libbasic/Attic/ExtStream.st,v 1.70 1995-11-23 01:48:32 cg Exp $'
 ! !
 
 !ExternalStream class methodsFor:'initialization'!
@@ -238,18 +237,23 @@
     ]
 ! !
 
+!ExternalStream class methodsFor:'instance creation'!
+
+new
+    |newStream|
+
+    newStream := self basicNew.
+    newStream text; buffered:true; useCRLF:false; clearEOF.
+    ^ newStream
+! !
+
 !ExternalStream class methodsFor:'Signal constants'!
 
-readErrorSignal
-    "return the signal raised on read errors"
-
-    ^ ReadErrorSignal
-!
-
-writeErrorSignal
-    "return the signal raised on write errors"
-
-    ^ WriteErrorSignal
+invalidModeSignal
+    "return the signal raised when doing text-I/O with a binary stream
+     or binary-I/O with a text stream"
+
+    ^ InvalidModeSignal
 !
 
 invalidReadSignal
@@ -264,11 +268,16 @@
     ^ InvalidWriteSignal
 !
 
-invalidModeSignal
-    "return the signal raised when doing text-I/O with a binary stream
-     or binary-I/O with a text stream"
-
-    ^ InvalidModeSignal
+openErrorSignal
+    "return the signal raised when a file open failed"
+
+    ^ OpenErrorSignal
+!
+
+readErrorSignal
+    "return the signal raised on read errors"
+
+    ^ ReadErrorSignal
 !
 
 streamNotOpenSignal
@@ -277,20 +286,10 @@
     ^ StreamNotOpenSignal
 !
 
-openErrorSignal
-    "return the signal raised when a file open failed"
-
-    ^ OpenErrorSignal
-! !
-
-!ExternalStream class methodsFor:'instance creation'!
-
-new
-    |newStream|
-
-    newStream := self basicNew.
-    newStream text; buffered:true; useCRLF:false; clearEOF.
-    ^ newStream
+writeErrorSignal
+    "return the signal raised on write errors"
+
+    ^ WriteErrorSignal
 ! !
 
 !ExternalStream class methodsFor:'error handling'!
@@ -315,278 +314,12 @@
     "
 ! !
 
-!ExternalStream methodsFor:'instance release'!
-
-shallowCopyForFinalization
-    "return a copy for finalization-registration;
-     since all we need at finalization time is the fileDescriptor,
-     a cheaper copy is possible."
-
-    ^ self class basicNew setFilePointer:filePointer
-!
-
-setFilePointer:anInteger
-    filePointer := anInteger
-!
-
-disposed
-    "some Stream has been collected - close the file if not already done"
-
-    self closeFile
-!
-
-shutDown
-    "close the stream - added for protocol compatibility with PipeStream.
-     see comment there"
-
-    self closeFile
-!
-
-closeFile
-    "low level close - may be redefined in subclasses"
-
-%{  /* NOCONTEXT */
-
-    OBJ fp;
-
-    if ((fp = _INST(filePointer)) != nil) {
-	_INST(filePointer) = nil;
-	__BEGIN_INTERRUPTABLE__
-	fclose(__FILEVal(fp));
-	__END_INTERRUPTABLE__
-    }
-%}
-! !
-
-!ExternalStream methodsFor:'private'!
-
-clearEOF
-    hitEOF := false
-!
-
-reOpen
-    "sent after snapin to reopen streams.
-     cannot reopen here since I am abstract and have no device knowledge"
-
-    self class name errorPrint. ': cannot reOpen stream - stream closed' errorPrintNL.
-    filePointer := nil.
-    Lobby unregister:self.
-!
-
-setLastError:aNumber
-    lastErrorNumber := aNumber
-! !
-
-!ExternalStream methodsFor:'error handling'!
-
-lastErrorNumber
-    "return the last error"
-
-    ^ lastErrorNumber
-!
-
-lastErrorString
-    "return a message string describing the last error"
-
-    (lastErrorNumber isNil or:[lastErrorNumber == 0]) ifTrue:[
-	^ 'I/O error'
-    ].
-    ^ OperatingSystem errorTextForNumber:lastErrorNumber
-!
-
-errorOpen
-    "report an error, that the stream is already opened"
-
-    ^ OpenErrorSignal
-	raiseRequestWith:self
-	errorString:(self class name , ' is already open')
-		 in:thisContext sender
-!
-
-openError
-    "report an error, that the open failed"
-
-    ^ OpenErrorSignal
-	raiseRequestWith:self
-	     errorString:('error on open: ' , self lastErrorString)
-		      in:thisContext sender
-!
-
-errorNotOpen
-    "report an error, that the stream has not been opened"
-
-    ^ StreamNotOpenSignal
-	raiseRequestWith:self
-	     errorString:(self class name , ' not open')
-		      in:thisContext sender
-!
-
-errorReadOnly
-    "report an error, that the stream is a readOnly stream"
-
-    ^ InvalidWriteSignal
-	raiseRequestWith:self
-	     errorString:(self class name , ' is readonly')
-		      in:thisContext sender
-!
-
-errorWriteOnly
-    "report an error, that the stream is a writeOnly stream"
-
-    ^ InvalidReadSignal
-	raiseRequestWith:self
-	     errorString:(self class name , ' is writeonly')
-		      in:thisContext sender
-!
-
-errorNotBinary
-    "report an error, that the stream is not in binary mode"
-
-    ^ InvalidModeSignal
-	raiseRequestWith:self
-	     errorString:(self class name , ' is not in binary mode')
-		      in:thisContext sender
-!
-
-errorBinary
-    "report an error, that the stream is in binary mode"
-
-    ^ InvalidModeSignal
-	raiseRequestWith:self
-	     errorString:(self class name , ' is in binary mode')
-		      in:thisContext sender
-!
-
-errorNotBuffered
-    "report an error, that the stream is not in buffered mode"
-
-    ^ StreamErrorSignal
-	raiseRequestWith:self
-	     errorString:(self class name , ' is unbuffered - operation not allowed')
-		      in:thisContext sender
-!
-
-ioError
-    "report an error, that some I/O error occured"
-
-    ^ StreamErrorSignal
-	raiseRequestWith:self
-	     errorString:('I/O error: ' , self lastErrorString)
-		      in:thisContext sender
-!
-
-readError
-    "report an error, that some read error occured"
-
-    ^ ReadErrorSignal
-	raiseRequestWith:self
-	     errorString:('read error: ' , self lastErrorString)
-		      in:thisContext sender
-!
-
-writeError
-    "report an error, that some write error occured"
-
-    ^ WriteErrorSignal
-	raiseRequestWith:self
-	     errorString:('write error: ' , self lastErrorString)
-		      in:thisContext sender
-!
-
-argumentMustBeInteger
-    "report an error, that the argument must be an integer"
-
-    ^ self error:'argument must be an integer'
-!
-
-argumentMustBeCharacter
-    "report an error, that the argument must be a character"
-
-    ^ self error:'argument must be a character'
-!
-
-argumentMustBeString
-    "report an error, that the argument must be a string"
-
-    ^ self error:'argument must be a string'
-! !
-
-!ExternalStream methodsFor:'queries'!
-
-isExternalStream
-    "return true, if the receiver is some kind of externalStream;
-     true is returned here - the method redefined from Object."
-
-    ^ true
-!
-
-isReadable 
-    "return true, if this stream can be read from"
-
-    ^ (mode ~~ #writeonly)
-!
-
-isWritable 
-    "return true, if this stream can be written to"
-
-    ^ (mode ~~ #readonly)
-!
-
-isBinary
-    "return true, if the stream is in binary (as opposed to text-) mode.
-     The default when created is false."
-
-    ^ binary
-! !
-
 !ExternalStream methodsFor:'accessing'!
 
-readonly
-    "set access mode to readonly"
-
-    mode := #readonly
-!
-
-writeonly
-    "set access mode to writeonly"
-
-    mode := #writeonly
-!
-
-readwrite
-    "set access mode to readwrite"
-
-    mode := #readwrite
-!
-
-filePointer
-    "return the filePointer of the receiver -
-     notice: for portability stdio is used; this means you will get
-     a FILE * - not a fileDescriptor. 
-     (what you really get is a corresponding integer).
-     You cannot do much with the returned value 
-     - except passing it to a primitive, for example."
-
-    ^ filePointer
-!
-
-fileDescriptor
-    "return the fileDescriptor of the receiver -
-     notice: this one returns the underlying OSs fileDescriptor -
-     this may not be available on all platforms (i.e. non unix systems)."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    OBJ fp;
-
-    if ((fp = _INST(filePointer)) != nil) {
-	f = __FILEVal(fp);
-	RETURN ( __MKSMALLINT(fileno(f)) );
-    }
-%}
-.
-    ^ self errorNotOpen
+binary
+    "switch to binary mode - default is text"
+
+    binary := true
 !
 
 buffered:aBoolean
@@ -595,40 +328,6 @@
     buffered := aBoolean
 !
 
-useCRLF:aBoolean
-    "turn on or off CRLF sending (instead of LF only) - default is off"
-
-    useCRLF := aBoolean
-!
-
-binary
-    "switch to binary mode - default is text"
-
-    binary := true
-!
-
-text
-    "switch to text mode - default is text"
-
-    binary := false
-!
-
-contentsSpecies
-    "return the kind of object to be returned by sub-collection builders
-     (such as upTo)"
-
-    binary ifTrue:[
-	^ ByteArray
-    ].
-    ^ String
-!
-
-contentsOfEntireFile
-    "ST-80 compatibility"
-
-    ^ self contents
-!
-
 contents
     "return the contents of the file from the current position up-to
      the end. If the stream is in binary mode, a ByteArray containing
@@ -677,1422 +376,259 @@
 	text add:l
     ].
     ^ text
-! !
-
-!ExternalStream methodsFor:'misc functions'!
-
-open
-    "open the stream
-     - this must be redefined in subclass"
-
-    ^ self subclassResponsibility
-!
-
-close
-    "close the stream - tell operating system"
-
-    filePointer isNil ifTrue:[^ self].
-    Lobby unregister:self.
-    self closeFile.
-    filePointer := nil
-!
-
-create
-    "create the stream
-     - this must be redefined in subclass"
-
-    ^ self subclassResponsibility
-!
-
-position
-    "return the position
-     - this must be redefined in subclass"
-
-    ^ self subclassResponsibility
-!
-
-position:anInteger
-    "set the position
-     - this must be redefined in subclass"
-
-    ^ self subclassResponsibility
-!
-
-backStep
-    "step back one element -
-     redefined, since position is redefined here"
-
-    self position:(self position - 1)
-!
-
-reset
-    "set the read position to the beginning of the collection"
-
-    self position:"0" 1
-!
-
-setToEnd
-    "redefined since it must be implemented differently"
-
-    ^ self subclassResponsibility
-!
-
-blocking:aBoolean
-    "set/clear the blocking attribute - if set (which is the default)
-     a read (using next) on the receiver will block until data is available.
-     If cleared, a read operation will immediately return with a value of
-     nil."
-
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    ^ OperatingSystem setBlocking:aBoolean on:(self fileDescriptor)
-!
-
-async:aBoolean
-    "set/clear the async attribute - if set the availability of data on 
-     the receiver will trigger an ioInterrupt.
-     If cleared (which is the default) no special notification is made."
-
-    |fd|
-
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    fd := self fileDescriptor.
-    aBoolean ifTrue:[
-	^ OperatingSystem enableIOInterruptsOn:fd
-    ].
-    ^ OperatingSystem disableIOInterruptsOn:fd
-!
-
-ioctl:ioctlNumber
-    "to provide a simple ioctl facility - an ioctl is performed
-     on the underlying file; no arguments are passed."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    int ret, ioNum, ioArg;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if ((fp = _INST(filePointer)) != nil) {
-	if (__isSmallInteger(ioctlNumber)) {
-	    ioNum = __intVal(ioctlNumber);
-	    f = __FILEVal(fp);
-
-	    __BEGIN_INTERRUPTABLE__
-	    do {
-		ret = ioctl(fileno(f), ioNum);
-	    } while ((ret < 0) && (errno == EINTR));
-	    __END_INTERRUPTABLE__
-
-	    if (ret >= 0) {
-		RETURN ( __MKSMALLINT(ret) );
-	    }
-	    _INST(position) = nil;
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self ioError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    "
-     ioctl-number is not an integer
-    "
-    ^ self primitiveFailed
-!
-
-ioctl:ioctlNumber with:arg
-    "to provide a simple ioctl facility - an ioctl is performed
-     on the underlying file; the argument is passed as argument.
-     If the argument is a number, its directly passed; if its a
-     kind of ByteArray (ByteArray, String or Structure) a pointer to
-     the data is passed. This allows performing most ioctls - however,
-     it might be tricky to setup the buffer."
-
-%{  /* NOCONTEXT */
-    FILE *f;
-    int ret, ioNum;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if ((fp = _INST(filePointer)) != nil) {
-	if (__isSmallInteger(ioctlNumber) 
-	 && (__isSmallInteger(arg) || __isBytes(arg))) {
-	    f = __FILEVal(fp);
-	    ioNum = __intVal(ioctlNumber);
-
-	    __BEGIN_INTERRUPTABLE__
-	    do {
-		if (__isSmallInteger(arg)) {
-		    ret = ioctl(fileno(f), ioNum, __intVal(arg));
-		} else {
-		    ret = ioctl(fileno(f), ioNum, __ByteArrayInstPtr(arg)->ba_element);
-		}
-	    } while ((ret < 0) && (errno == EINTR));
-	    __END_INTERRUPTABLE__
-
-	    if (ret >= 0) {
-		RETURN ( __MKSMALLINT(ret) );
-	    }
-	    _INST(position) = nil;
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self ioError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    "
-     ioctl-number is not an integer or argument is not byteArray-like
-    "
-    ^ self primitiveFailed
-! !
-
-!ExternalStream methodsFor:'non homogenous reading'!
-
-nextByte
-    "read the next byte and return it as an Integer; return nil on error.
-     This is allowed in both text and binary modes, always returning the
-     bytes binary value as an integer in 0..255."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    unsigned char byte;
-    int cnt;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	f = __FILEVal(fp);
-
-	if (_INST(buffered) == true) {
-	    __READING__(f)
-	}
-
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    if (_INST(buffered) == false) {
-		cnt = read(fileno(f), &byte, 1);
-	    } else {
-		cnt = fread(&byte, 1, 1, f);
-	    }
-	} while ((cnt < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-
-	if (cnt == 1) {
-	    if (_INST(position) != nil)
-		_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 1);
-	    RETURN ( __MKSMALLINT(byte) );
-	}
-	if (cnt == 0) {
-	    _INST(hitEOF) = true;
-/*
-	    if (errno == EWOULDBLOCK) {
-		RETURN (nil);
-	    }
-*/
-	}
-	_INST(position) = nil;
-	_INST(lastErrorNumber) = __MKSMALLINT(errno);
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    ^ self errorWriteOnly
-!
-
-nextBytesInto:anObject
-    "read bytes into an object, regardless of binary/text mode.
-     The number of bytes to read is defined by the objects size.
-     Return the number of bytes read. On EOF, 0 is returned.
-     If the receiver is some socket/pipe-like stream, an exception
-     is raised if the connection is broken.
-
-     The object to read into must have non-pointer indexed instvars 
-     (i.e. it must be a ByteArray, String, Float- or DoubleArray).     
-     If anObject is a string or byteArray and reused, this provides the
-     fastest possible physical I/O (since no new objects are allocated).
-
-     Use with care - non object oriented i/o.
-     Warning: in general, you cannot use this method to pass data from other 
-     architectures since it does not care for byte order or float representation."
-
-    ^ self nextBytes:(anObject size) into:anObject startingAt:1
-
-    " to read 100 bytes from a stream:
-    
-     |b aStream|
-
-     aStream := 'smalltalk.rc' asFilename readStream.
-     b := ByteArray new:100.
-     aStream nextBytesInto:b.
-     aStream close.
-     b inspect
-    "
-
-    "
-     |s aStream|
-     aStream := 'smalltalk.rc' asFilename readStream.
-     s := String new:100.
-     aStream nextBytesInto:s.
-     aStream close.
-     s inspect
-    "
-!
-
-nextBytes:count into:anObject
-    "read the next count bytes into an object and return the number of
-     bytes read. On EOF, 0 is returned.
-     If the receiver is some socket/pipe-like stream, an exception
-     is raised if the connection is broken.
-
-     The object must have non-pointer indexed instvars (i.e. it must be 
-     a ByteArray, String, Float- or DoubleArray).
-     If anObject is a string or byteArray and reused, this provides the
-     fastest possible physical I/O (since no new objects are allocated).
-
-     Use with care - non object oriented i/o.
-     Warning: in general, you cannot use this method to pass data from other 
-     architectures since it does not care for byte order or float representation."
-
-    ^ self nextBytes:count into:anObject startingAt:1
 !
 
-nextBytes:count into:anObject startingAt:start
-    "read the next count bytes into an object and return the number of
-     bytes read or 0 on EOF. 
-     If the receiver is some socket/pipe-like stream, an exception
-     is raised if the connection is broken.
-     Notice, that in contrast to other methods
-     here, this does NOT return nil on EOF, but the actual count.
-     Thus allowing read of partial blocks.
-
-     The object must have non-pointer indexed instvars 
-     (i.e. it must be a ByteArray, String, Float- or DoubleArray).
-     If anObject is a string or byteArray and reused, this provides the
-     fastest possible physical I/O (since no new objects are allocated).
-
-     Use with care - non object oriented I/O.
-     Warning: in general, you cannot use this method to pass data from other 
-     architectures since it does not care for byte order or float representation."
-
-%{
-    FILE *f;
-    int cnt, offs, ret;
-    int objSize, nInstVars, nInstBytes;
-    char *cp;
-    OBJ pos, fp, oClass;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	if (__bothSmallInteger(count, start)) {
-	    f = __FILEVal(fp);
-
-	    oClass = __Class(anObject);
-	    switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
-		case BYTEARRAY:
-		case WORDARRAY:
-		case LONGARRAY:
-		case FLOATARRAY:
-		case DOUBLEARRAY:
-		    break;
-		default:
-		    goto bad;
-	    }
-	    cnt = __intVal(count);
-	    offs = __intVal(start) - 1;
-	    nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	    nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
-	    objSize = __Size(anObject) - nInstBytes;
-	    if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
-		/* 
-		 * mhmh - since we are interruptable, anObject may move.
-		 * therefore, fetch the cp-pointer within the loop
-		 */
-		if (_INST(buffered) == true) {
-		    __READING__(f)
-		}
-
-		__BEGIN_INTERRUPTABLE__
-		do {
-		    errno = 0;
-		    /*
-		     * because we are interruptable, refetch pointer
-		     */
-		    cp = (char *)__InstPtr(anObject) + nInstBytes + offs;
-		    if (_INST(buffered) == false) {
-			ret = read(fileno(f), cp, cnt);
-		    } else {
-			if (feof(f)) {
-			    ret = 0;
-			    break;
-			}
-			ret = fread(cp, 1, cnt, f);
-		    }
-		} while ((ret < 0) && (errno == EINTR));
-
-		__END_INTERRUPTABLE__
-		cnt = ret;
-
-		if (cnt > 0) {
-		    pos = _INST(position);
-		    if (pos != nil) {
-			_INST(position) = __MKSMALLINT(__intVal(pos) + cnt);
-		    }
-		    RETURN (__MKSMALLINT(cnt));
-		}
-		if (cnt == 0) { 
-		    _INST(hitEOF) = true;
-		    RETURN (__MKSMALLINT(cnt));
-		}
-
-		_INST(position) = nil;
-		_INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    }
-	}
-    }
-bad: ;
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    "
-     count not integer or arg not bit-like (String, ByteArray etc)
-    "
-    ^ self primitiveFailed
-!
-
-nextShortMSB:msbFlag
-    "Read two bytes and return the value as a 16-bit signed Integer.
-     If msbFlag is true, value is read with most-significant byte first, 
-     otherwise least-significant byte comes first.
-     A nil is returned if EOF is reached (also when EOF is hit after the first byte).
-     Works in both binary and text modes."
-
-%{  /* NOCONTEXT */
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	FILE *f;
-	int first, second, err;
-	short value;
-
-	f = __FILEVal(fp);
-	__BEGIN_INTERRUPTABLE__
-	__READING__(f)
-
-	do {
-	    first = getc(f);
-	} while ((first < 0) && (errno == EINTR));
-
-	if (first != EOF) {
-	    do {
-		second = getc(f);
-	    } while ((second < 0) && (errno == EINTR));
-
-	    __END_INTERRUPTABLE__
-	    if (second != EOF) {
-		if (_INST(position) != nil) {
-		    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 2);
-		}
-		if (msbFlag == true) {
-		    value = ((first & 0xFF) << 8) | (second & 0xFF);
-		} else {
-		    value = ((second & 0xFF) << 8) | (first & 0xFF);
-		}
-		RETURN (__MKSMALLINT(value));
-	    }
-	}
-	__END_INTERRUPTABLE__
-
-	if (ferror(f) && (errno != 0)) {
-	    _INST(position) = nil;
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	} else {
-	    _INST(hitEOF) = true;
-	    RETURN (nil);
-	}
-    }
-%}.
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    ^ self readError.
+contentsOfEntireFile
+    "ST-80 compatibility"
+
+    ^ self contents
 !
 
-nextUnsignedShortMSB:msbFlag
-    "Read two bytes and return the value as a 16-bit unsigned Integer.
-     If msbFlag is true, value is read with most-significant byte first, otherwise
-     least-significant byte comes first.
-     A nil is returned if EOF is reached (also when EOF is hit after the first byte).
-     Works in both binary and text modes."
-
-%{  /* NOCONTEXT */
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	FILE *f;
-	int first, second;
-	unsigned value;
-
-	f = __FILEVal(fp);
-	__BEGIN_INTERRUPTABLE__
-	__READING__(f)
-
-	do {
-	    first = getc(f);
-	} while ((first < 0) && (errno == EINTR));
-
-	if (first != EOF) {
-	    do {
-		second = getc(f);
-	    } while ((second < 0) && (errno == EINTR));
-
-	    __END_INTERRUPTABLE__
-	    if (second != EOF) {
-		if (_INST(position) != nil) {
-		    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 2);
-		}
-		if (msbFlag == true) {
-		    value = ((first & 0xFF) << 8) | (second & 0xFF);
-		} else {
-		    value = ((second & 0xFF) << 8) | (first & 0xFF);
-		}
-		RETURN (__MKSMALLINT(value));
-	    }
-	}
-	__END_INTERRUPTABLE__
-
-	if (ferror(f) && (errno != 0)) {
-	    _INST(position) = nil;
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	} else {
-	    _INST(hitEOF) = true;
-	    RETURN (nil);
-	}
-    }
-%}.
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    ^ self readError.
-!
-
-nextLongMSB:msbFlag
-    "Read four bytes and return the value as a 32-bit signed Integer, 
-     which may be a LargeInteger.
-     If msbFlag is true, value is read with most-significant byte first, 
-     otherwise least-significant byte comes first.
-     A nil is returned, if EOF is hit before all 4 bytes have been read.
-     Works in both binary and text modes."
-
-%{  /* NOCONTEXT */
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	FILE *f;
-	int first, second, third, fourth;
-	int value;
-
-	f = __FILEVal(fp);
-	__BEGIN_INTERRUPTABLE__
-	__READING__(f)
-
-	do {
-	    first = getc(f);
-	} while ((first < 0) && (errno == EINTR));
-	if (first != EOF) {
-	    do {
-		second = getc(f);
-	    } while ((second < 0) && (errno == EINTR));
-	    if (second != EOF) {
-		do {
-		    third = getc(f);
-		} while ((third < 0) && (errno == EINTR));
-		if (third != EOF) {
-		    do {
-			fourth = getc(f);
-		    } while ((fourth < 0) && (errno == EINTR));
-		    if (fourth != EOF) {
-			__END_INTERRUPTABLE__
-
-			if (msbFlag == true) {
-			    value = (first & 0xFF);
-			    value = (value<<8) | (second & 0xFF);
-			    value = (value<<8) | (third & 0xFF);
-			    value = (value<<8) | (fourth & 0xFF);
-			} else {
-			    value = (fourth & 0xFF);
-			    value = (value<<8) | (third & 0xFF);
-			    value = (value<<8) | (second & 0xFF);
-			    value = (value<<8) | (first & 0xFF);
-			}
-			if (_INST(position) != nil) {
-			    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 4);
-			}
-			if ((value >= _MIN_INT) && (value <= _MAX_INT)) {
-			    RETURN ( __MKSMALLINT(value));
-			}
-			RETURN ( _MKLARGEINT(value) );
-		    }
-		}
-	    }
-	}
-	__END_INTERRUPTABLE__
-
-	if (ferror(f) && (errno != 0)) {
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    _INST(position) = nil;
-	} else {
-	    _INST(hitEOF) = true;
-	    RETURN (nil);
-	}
-    }
-%}.
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    ^ self readError.
-!
-
-nextUnsignedLongMSB:msbFlag
-    "Read four bytes and return the value as a 32-bit unsigned Integer, which may be
-     a LargeInteger.
-     If msbFlag is true, value is read with most-significant byte first, otherwise
-     least-significant byte comes first.
-     A nil is returned, if endOfFile occurs before all 4 bytes have been read.
-     Works in both binary and text modes."
-
-%{  /* NOCONTEXT */
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	FILE *f;
-	int first, second, third, fourth;
-	unsigned int value;
-
-	f = __FILEVal(fp);
-	__BEGIN_INTERRUPTABLE__
-	__READING__(f)
-
-	do {
-	    first = getc(f);
-	} while ((first < 0) && (errno == EINTR));
-	if (first != EOF) {
-	    do {
-		second = getc(f);
-	    } while ((second < 0) && (errno == EINTR));
-	    if (second != EOF) {
-		do {
-		    third = getc(f);
-		} while ((third < 0) && (errno == EINTR));
-		if (third != EOF) {
-		    do {
-			fourth = getc(f);
-		    } while ((fourth < 0) && (errno == EINTR));
-		    if (fourth != EOF) {
-			__END_INTERRUPTABLE__
-
-			if (msbFlag == true) {
-			    value = (first & 0xFF);
-			    value = (value<<8) | (second & 0xFF);
-			    value = (value<<8) | (third & 0xFF);
-			    value = (value<<8) | (fourth & 0xFF);
-			} else {
-			    value = (fourth & 0xFF);
-			    value = (value<<8) | (third & 0xFF);
-			    value = (value<<8) | (second & 0xFF);
-			    value = (value<<8) | (first & 0xFF);
-			}
-			if (_INST(position) != nil) {
-			    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 4);
-			}
-			if (value <= _MAX_INT) {
-			    RETURN ( __MKSMALLINT(value));
-			}
-			RETURN ( _MKULARGEINT(value) );
-		    }
-		}
-	    }
-	}
-	__END_INTERRUPTABLE__
-
-	if (ferror(f) && (errno != 0)) {
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    _INST(position) = nil;
-	} else {
-	    _INST(hitEOF) = true;
-	    RETURN (nil);
-	}
-    }
-%}.
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    ^ self readError.
-!
-
-nextWord
-    "in text-mode:
-	 read the alphaNumeric next word (i.e. up to non letter-or-digit).
-	 return a string containing those characters.
-     in binary-mode:
-	 read two bytes (msb-first) and return the value as a 16-bit 
-	 unsigned Integer (for compatibility with other smalltalks)"
+contentsSpecies
+    "return the kind of object to be returned by sub-collection builders
+     (such as upTo)"
 
     binary ifTrue:[
-	^ self nextUnsignedShortMSB:true
+	^ ByteArray
     ].
-    ^ self nextAlphaNumericWord
+    ^ String
 !
 
-nextLong
-    "Read four bytes (msb-first) and return the value as a 32-bit signed Integer.
-     The returned value may be a LargeInteger.
-     (msb-first for compatibility with other smalltalks)"
-
-    ^ self nextUnsignedLongMSB:true
-! !
-
-!ExternalStream methodsFor:'non homogenous writing'!
-
-nextPutByte:aByteValue
-    "write a byte.
-     Works in both binary and text modes."
+fileDescriptor
+    "return the fileDescriptor of the receiver -
+     notice: this one returns the underlying OSs fileDescriptor -
+     this may not be available on all platforms (i.e. non unix systems)."
 
 %{  /* NOCONTEXT */
 
     FILE *f;
-    char c;
-    OBJ pos, fp;
-    int cnt;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))) {
-	if (__isSmallInteger(aByteValue)) {
-	    c = __intVal(aByteValue);
-	    f = __FILEVal(fp);
-	    __BEGIN_INTERRUPTABLE__
-/*
- *#ifdef OLD
- *          if (_INST(buffered) == false) {
- *              cnt = write(fileno(f), &c, 1);
- *          } else 
- *#endif
- *          {
- *              __WRITING__(f)
- *              cnt = fwrite(&c, 1, 1, f);
- *#ifndef OLD
- *              if (_INST(buffered) == false) {
- *                  fflush(f);
- *              }
- *#endif
- *          }
- */
-	    if (_INST(buffered) == true) {
-		__WRITING__(f)
-		cnt = fwrite(&c, 1, 1, f);
-	    } else {
-		do {
-		    cnt = write(fileno(f), &c, 1);
-		} while ((cnt < 0) && (errno == EINTR));
-	    }
-	    __END_INTERRUPTABLE__
-
-	    if (cnt == 1) {
-		pos = _INST(position);
-		if (pos != nil)
-		    _INST(position) = __MKSMALLINT(__intVal(pos) + 1);
-		RETURN (self);
-	    }
-	    if (cnt < 0) {
-		_INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    }
-	}
+    OBJ fp;
+
+    if ((fp = _INST(filePointer)) != nil) {
+	f = __FILEVal(fp);
+	RETURN ( __MKSMALLINT(fileno(f)) );
     }
-%}.
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-    ^ self writeError.
+%}
+.
+    ^ self errorNotOpen
+!
+
+filePointer
+    "return the filePointer of the receiver -
+     notice: for portability stdio is used; this means you will get
+     a FILE * - not a fileDescriptor. 
+     (what you really get is a corresponding integer).
+     You cannot do much with the returned value 
+     - except passing it to a primitive, for example."
+
+    ^ filePointer
+!
+
+readonly
+    "set access mode to readonly"
+
+    mode := #readonly
+!
+
+readwrite
+    "set access mode to readwrite"
+
+    mode := #readwrite
+!
+
+text
+    "switch to text mode - default is text"
+
+    binary := false
+!
+
+useCRLF:aBoolean
+    "turn on or off CRLF sending (instead of LF only) - default is off"
+
+    useCRLF := aBoolean
 !
 
-nextPutBytesFrom:anObject
-    "write bytes from an object; the number of bytes is defined by
-     the objects size.
-     Return the number of bytes written or nil on error.
-     The object must have non-pointer indexed instvars 
-     (i.e. be a ByteArray, String, Float- or DoubleArray).     
-     Use with care - non object oriented i/o.
-     Warning: in general, you cannot use this method to pass data to other 
-     architectures since it does not care for byte order or float representation."
-
-    ^ self nextPutBytes:(anObject size) from:anObject startingAt:1
+writeonly
+    "set access mode to writeonly"
+
+    mode := #writeonly
+! !
+
+!ExternalStream methodsFor:'error handling'!
+
+argumentMustBeCharacter
+    "report an error, that the argument must be a character"
+
+    ^ self error:'argument must be a character'
+!
+
+argumentMustBeInteger
+    "report an error, that the argument must be an integer"
+
+    ^ self error:'argument must be an integer'
 !
 
-nextPutBytes:count from:anObject
-    "write count bytes from an object.
-     Return the number of bytes written or nil on error.
-     The object must have non-pointer indexed instvars 
-     (i.e. be a ByteArray, String, Float- or DoubleArray).     
-     Use with care - non object oriented i/o.
-     Warning: in general, you cannot use this method to pass data to other 
-     architectures since it does not care for byte order or float representation."
-
-    ^ self nextPutBytes:count from:anObject startingAt:1
+argumentMustBeString
+    "report an error, that the argument must be a string"
+
+    ^ self error:'argument must be a string'
+!
+
+errorBinary
+    "report an error, that the stream is in binary mode"
+
+    ^ InvalidModeSignal
+	raiseRequestWith:self
+	     errorString:(self class name , ' is in binary mode')
+		      in:thisContext sender
+!
+
+errorNotBinary
+    "report an error, that the stream is not in binary mode"
+
+    ^ InvalidModeSignal
+	raiseRequestWith:self
+	     errorString:(self class name , ' is not in binary mode')
+		      in:thisContext sender
 !
 
-nextPutBytes:count from:anObject startingAt:start
-    "write count bytes from an object starting at index start.
-     return the number of bytes written - which could be 0.
-     The object must have non-pointer indexed instvars 
-     (i.e. be a ByteArray, String, Float- or DoubleArray).     
-     Use with care - non object oriented i/o.
-     Warning: in general, you cannot use this method to pass data to other 
-     architectures since it does not care for byte order or float representation."
-
-%{  /* NOCONTEXT */
-    FILE *f;
-    int cnt, offs;
-    int objSize, nInstVars, nInstBytes;
-    char *cp;
-    OBJ oClass, pos, fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))) {
-	if (__bothSmallInteger(count, start)) {
-	    oClass = __Class(anObject);
-	    switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
-		case BYTEARRAY:
-		case WORDARRAY:
-		case LONGARRAY:
-		case FLOATARRAY:
-		case DOUBLEARRAY:
-		    break;
-		default:
-		    goto bad;
-	    }
-	    cnt = __intVal(count);
-	    offs = __intVal(start) - 1;
-	    f = __FILEVal(fp);
-
-	    nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	    nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
-	    objSize = __Size(anObject) - nInstBytes;
-	    if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
-		cp = (char *)__InstPtr(anObject) + nInstBytes + offs;
-		__BEGIN_INTERRUPTABLE__
-
-		if (_INST(buffered) == true) {
-		    __WRITING__(f)
-		    cnt = fwrite(cp, 1, cnt, f);
-		} else {
-		    do {
-			cp = (char *)__InstPtr(anObject) + nInstBytes + offs;
-			cnt = write(fileno(f), cp, cnt);
-		    } while ((cnt < 0) && (errno == EINTR));
-		}
-
-		__END_INTERRUPTABLE__
-
-		if (cnt >= 0) {
-		    pos = _INST(position);
-		    if (pos != nil)
-			_INST(position) = __MKSMALLINT(__intVal(pos) + cnt);
-		    RETURN ( __MKSMALLINT(cnt) );
-		}
-		_INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    }
-	}
-    }
-bad: ;
-%}.
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-    ^ self primitiveFailed
+errorNotBuffered
+    "report an error, that the stream is not in buffered mode"
+
+    ^ StreamErrorSignal
+	raiseRequestWith:self
+	     errorString:(self class name , ' is unbuffered - operation not allowed')
+		      in:thisContext sender
+!
+
+errorNotOpen
+    "report an error, that the stream has not been opened"
+
+    ^ StreamNotOpenSignal
+	raiseRequestWith:self
+	     errorString:(self class name , ' not open')
+		      in:thisContext sender
+!
+
+errorOpen
+    "report an error, that the stream is already opened"
+
+    ^ OpenErrorSignal
+	raiseRequestWith:self
+	errorString:(self class name , ' is already open')
+		 in:thisContext sender
+!
+
+errorReadOnly
+    "report an error, that the stream is a readOnly stream"
+
+    ^ InvalidWriteSignal
+	raiseRequestWith:self
+	     errorString:(self class name , ' is readonly')
+		      in:thisContext sender
+!
+
+errorWriteOnly
+    "report an error, that the stream is a writeOnly stream"
+
+    ^ InvalidReadSignal
+	raiseRequestWith:self
+	     errorString:(self class name , ' is writeonly')
+		      in:thisContext sender
 !
 
-nextPutShort:aNumber MSB:msbFlag
-    "Write the argument, aNumber as a short (two bytes). If msbFlag is
-     true, data is written most-significant byte first; otherwise least
-     first.
-     Works in both binary and text modes."
-
-%{  /* NOCONTEXT */
-
-    int num;
-    char bytes[2];
-    FILE *f;
-    int cnt;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))
-     && __isSmallInteger(aNumber)) {
-	num = __intVal(aNumber);
-	if (msbFlag == true) {
-	    bytes[0] = (num >> 8) & 0xFF;
-	    bytes[1] = num & 0xFF;
-	} else {
-	    bytes[1] = (num >> 8) & 0xFF;
-	    bytes[0] = num & 0xFF;
-	}
-
-	f = __FILEVal(fp);
-	__BEGIN_INTERRUPTABLE__
-
-	if (_INST(buffered) == true) {
-	    __WRITING__(f)
-	    cnt = fwrite(bytes, 1, 2, f);
-	} else {
-	    do {
-		cnt = write(fileno(f), bytes, 2);
-	    } while ((cnt < 0) && (errno == EINTR));
-	}
-
-	__END_INTERRUPTABLE__
-
-	if (cnt == 2) {
-	    if (_INST(position) != nil) {
-		_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 2);
-	    }
-	    RETURN ( self );
-	}
-	_INST(lastErrorNumber) = __MKSMALLINT(errno);
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-    self argumentMustBeInteger
+ioError
+    "report an error, that some I/O error occured"
+
+    ^ StreamErrorSignal
+	raiseRequestWith:self
+	     errorString:('I/O error: ' , self lastErrorString)
+		      in:thisContext sender
+!
+
+lastErrorNumber
+    "return the last error"
+
+    ^ lastErrorNumber
+!
+
+lastErrorString
+    "return a message string describing the last error"
+
+    (lastErrorNumber isNil or:[lastErrorNumber == 0]) ifTrue:[
+	^ 'I/O error'
+    ].
+    ^ OperatingSystem errorTextForNumber:lastErrorNumber
 !
 
-nextPutLong:aNumber MSB:msbFlag
-    "Write the argument, aNumber as a long (four bytes). If msbFlag is
-     true, data is written most-significant byte first; otherwise least
-     first.
-     Works in both binary and text modes."
+openError
+    "report an error, that the open failed"
+
+    ^ OpenErrorSignal
+	raiseRequestWith:self
+	     errorString:('error on open: ' , self lastErrorString)
+		      in:thisContext sender
+!
+
+readError
+    "report an error, that some read error occured"
+
+    ^ ReadErrorSignal
+	raiseRequestWith:self
+	     errorString:('read error: ' , self lastErrorString)
+		      in:thisContext sender
+!
+
+writeError
+    "report an error, that some write error occured"
+
+    ^ WriteErrorSignal
+	raiseRequestWith:self
+	     errorString:('write error: ' , self lastErrorString)
+		      in:thisContext sender
+! !
+
+!ExternalStream methodsFor:'instance release'!
+
+closeFile
+    "low level close - may be redefined in subclasses"
 
 %{  /* NOCONTEXT */
 
-    int num;
-    char bytes[4];
-    FILE *f;
-    int cnt;
     OBJ fp;
 
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))
-     && __isSmallInteger(aNumber)) {
-	num = __intVal(aNumber);
-	if (msbFlag == true) {
-	    bytes[0] = (num >> 24) & 0xFF;
-	    bytes[1] = (num >> 16) & 0xFF;
-	    bytes[2] = (num >> 8) & 0xFF;
-	    bytes[3] = num & 0xFF;
-	} else {
-	    bytes[3] = (num >> 24) & 0xFF;
-	    bytes[2] = (num >> 16) & 0xFF;
-	    bytes[1] = (num >> 8) & 0xFF;
-	    bytes[0] = num & 0xFF;
-	}
-
-	f = __FILEVal(fp);
+    if ((fp = _INST(filePointer)) != nil) {
+	_INST(filePointer) = nil;
 	__BEGIN_INTERRUPTABLE__
-
-	if (_INST(buffered) == true) {
-	    __WRITING__(f)
-	    cnt = fwrite(bytes, 1, 4, f);
-	} else {
-	    do {
-		cnt = write(fileno(f), bytes, 4);
-	    } while ((cnt < 0) && (errno == EINTR));
-	}
-
+	fclose(__FILEVal(fp));
 	__END_INTERRUPTABLE__
-
-	if (cnt == 4) {
-	    if (_INST(position) != nil) {
-		_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 4);
-	    }
-	    RETURN ( self );
-	}
-	_INST(lastErrorNumber) = __MKSMALLINT(errno);
-    }
-%}.
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-
-    aNumber isInteger ifTrue:[
-	msbFlag ifTrue:[
-	    "high word first"
-	    (self nextShortPut:(aNumber // 16r10000) MSB:true) isNil ifTrue:[^ nil].
-	    ^ self nextShortPut:(aNumber \\ 16r10000) MSB:true
-	].
-	"low word first"
-	(self nextShortPut:(aNumber \\ 16r10000) MSB:false) isNil ifTrue:[^ nil].
-	^ self nextShortPut:(aNumber // 16r10000) MSB:false.
-    ].
-    self argumentMustBeInteger
-! !
-
-!ExternalStream methodsFor:'reading'!
-
-peek
-    "return the element to be read next without advancing read position.
-     In binary mode, an integer is returned, otherwise a character.
-     If there are no more elements, nil is returned.
-     Not allowed in unbuffered mode."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    REGISTER int c;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-#ifdef OLD
-	if (_INST(buffered) == true) 
-#endif
-	{
-	    f = __FILEVal(fp);
-
-	    __BEGIN_INTERRUPTABLE__
-	    __READING__(f)
-
-	    do {
-		c = getc(f);
-	    } while ((c < 0) && (errno == EINTR));
-	    __END_INTERRUPTABLE__
-
-	    if (c != EOF) {
-		ungetc(c, f);
-		if (_INST(binary) == true) {
-		    RETURN ( __MKSMALLINT(c & 0xFF) );
-		}
-		RETURN ( _MKCHARACTER(c & 0xFF) );
-	    }
-	    if (ferror(f) && (errno != 0)) {
-		_INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    } else {
-		_INST(hitEOF) = true;
-		RETURN ( nil );
-	    }
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    buffered ifFalse:[^ self errorNotBuffered].
-    ^ self errorWriteOnly
-!
-
-next
-    "return the next element; advance read position.
-     In binary mode, an integer is returned, otherwise a character.
-     If there are no more elements, nil is returned."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    int c;
-    OBJ pos, fp;
-    unsigned char ch;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	f = __FILEVal(fp);
-	__BEGIN_INTERRUPTABLE__
-
-	if (_INST(buffered) == true) {
-	    __READING__(f)
-	}
-
-	do {
-	    errno = 0;
-	    if (_INST(buffered) == false) {
-		if (read(fileno(f), &ch, 1) != 1)
-		    c = EOF;
-		else
-		    c = ch;
-	    } else 
-	    {
-		c = getc(f);
-	    }
-	} while ((c < 0) && (errno == EINTR));
-
-	__END_INTERRUPTABLE__
-
-	if (c != EOF) {
-	    pos = _INST(position);
-	    if (__isSmallInteger(pos)) {
-		_INST(position) = __MKSMALLINT(__intVal(pos) + 1);
-	    } else {
-		_INST(position) = nil;
-	    }
-	    if (_INST(binary) == true) {
-		RETURN ( __MKSMALLINT(c & 0xFF) );
-	    }
-	    RETURN ( _MKCHARACTER(c & 0xFF) );
-	}
-/*
-	if (errno == EWOULDBLOCK) {
-	    _INST(hitEOF) = true;
-	    RETURN(nil);
-	}
-*/
-	_INST(position) = nil;
-        
-	if ((_INST(buffered) == false)
-	 || (ferror(f) && (errno != 0))) {
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	} else {
-	    _INST(hitEOF) = true;
-	    RETURN ( nil );
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    self errorWriteOnly
-!
-
-next:count
-    "return the next count elements of the stream as a collection.
-     Redefined to return a String or ByteArray instead of the default: Array."
-
-    |coll|
-
-    binary ifTrue:[
-	coll := ByteArray uninitializedNew:count
-    ] ifFalse:[
-	coll := String new:count
-    ].
-    "/
-    "/ Q: should we use: 
-    "/    self nextBytes:count into:coll startingAt:1
-    "/
-    1 to:count do: [:index |
-	coll at:index put:(self next)
-    ].
-    ^ coll
-! !
-
-!ExternalStream methodsFor:'writing'!
-
-commit
-    "write all buffered date - ignored if unbuffered"
-
-    self synchronizeOutput
-!
-
-synchronizeOutput
-    "write all buffered data - ignored if unbuffered"
-
-%{  /* NOCONTEXT */
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if ((fp = _INST(filePointer)) != nil) {
-	if (_INST(mode) != @symbol(readonly)) {
-	    if (_INST(buffered) == true) {
-		__BEGIN_INTERRUPTABLE__
-		fflush( __FILEVal(fp) );
-		__END_INTERRUPTABLE__
-	    }
-	}
     }
 %}
 !
 
-nextPut:aCharacter
-    "write the argument, aCharacter - return nil if failed, self if ok.
-     Only single-byte characters are currently supported"
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    char c;
-    int cnt;
-    OBJ pos, fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil) 
-     && (_INST(mode) != @symbol(readonly))) {
-	if (_INST(binary) != true) {
-	    if (__isCharacter(aCharacter)) {
-		c = __intVal(__characterVal(aCharacter)) & 0xFF;
-    doWrite:
-		f = __FILEVal(fp);
-
-		__BEGIN_INTERRUPTABLE__
-
-		if (_INST(buffered) == true) {
-		    __WRITING__(f)
-
-		    do {
-			cnt = fwrite(&c, 1, 1, f);
-		    } while ((cnt != 1) && (errno == EINTR));
-		} else {
-		    do {
-			cnt = write(fileno(f), &c, 1);
-		    } while ((cnt != 1) && (errno == EINTR));
-		}
-
-		__END_INTERRUPTABLE__
-
-		if (cnt == 1) {
-		    pos = _INST(position);
-		    if (pos != nil) {
-			_INST(position) = __MKSMALLINT(__intVal(pos) + 1);
-		    }
-		    RETURN ( self );
-		}
-		_INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    }
-	} else {
-	    if (__isSmallInteger(aCharacter)) {
-		c = __intVal(aCharacter);
-		goto doWrite;
-	    }
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-    binary ifFalse:[^ self argumentMustBeCharacter].
-    ^ self argumentMustBeInteger.
+disposed
+    "some Stream has been collected - close the file if not already done"
+
+    self closeFile
+!
+
+setFilePointer:anInteger
+    filePointer := anInteger
 !
 
-nextPutAll:aCollection
-    "write all elements of the argument, aCollection.
-     Reimplemented for speed when writing strings or byteArrays.
-     For others, falls back to general method in superclass."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    unsigned char *cp;
-    int len, cnt;
-    OBJ pos, fp;
-    int offs;
-
-    _INST(lastErrorNumber) = nil;
-
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))) {
-	cp = NULL;
-	offs = 0;
-	if (__isString(aCollection) || __isSymbol(aCollection)) {
-	    cp = _stringVal(aCollection);
-	    len = _stringSize(aCollection);
-	} else {
-	    if (_INST(binary) == true) {
-		if (__isByteArray(aCollection)) {
-		    cp = __ByteArrayInstPtr(aCollection)->ba_element;
-		    len = _byteArraySize(aCollection);
-		} else {
-		    if (__isBytes(aCollection)) {
-			int nInst;
-
-			cp = __ByteArrayInstPtr(aCollection)->ba_element;
-			len = _byteArraySize(aCollection);
-			nInst = __intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars);
-			offs = __OBJS2BYTES__(nInst);
-			cp += offs;
-			len -= offs;
-		    }
-		}
-	    }
-	}
-	if (cp != NULL) {
-	    f = __FILEVal(fp);
-
-	    __BEGIN_INTERRUPTABLE__
-
-	    if (_INST(buffered) == false) {
-		int cc, rest;
-
-		cnt = 0;
-		do {
-		    /*
-		     * refetch pointer in case of an interrupt
-		     */
-		    cp = __ByteArrayInstPtr(aCollection)->ba_element + offs;
-		    cnt = write(fileno(f), cp, len);
-		} while ((cnt < 0) && (errno == EINTR));
-	    } else {
-		__WRITING__(f)
-		cnt = fwrite(cp, 1, len, f);
-		if (errno == EINTR) errno = 0;
-	    }
-
-	    __END_INTERRUPTABLE__
-
-	    if (cnt == len) {
-		pos = _INST(position);
-		if (pos != nil) {
-		    _INST(position) = __MKSMALLINT(__intVal(pos) + len);
-		}
-		RETURN ( self );
-	    }
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-
-    ^ super nextPutAll:aCollection
+shallowCopyForFinalization
+    "return a copy for finalization-registration;
+     since all we need at finalization time is the fileDescriptor,
+     a cheaper copy is possible."
+
+    ^ self class basicNew setFilePointer:filePointer
 !
 
-nextPutAll:aCollection startingAt:start to:stop
-    "write a range of elements of the argument, aCollection.
-     Reimplemented for speed when writing strings or byteArrays.
-     For others, falls back to general method in superclass."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    unsigned char *cp;
-    int offs, len, cnt, index1, index2;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))) {
-	if (__bothSmallInteger(start, stop)) {
-	    cp = NULL;
-	    offs = 0;
-	    if (_INST(binary) != true) {
-		if (__isString(aCollection) || __isSymbol(aCollection)) {
-		    cp = _stringVal(aCollection);
-		    len = _stringSize(aCollection);
-		}
-	    } else {
-		if (__isByteArray(aCollection)) {
-		    cp = __ByteArrayInstPtr(aCollection)->ba_element;
-		    len = _byteArraySize(aCollection);
-		} else {
-		    if (__isBytes(aCollection)) {
-			int nInst;
-
-			cp = __ByteArrayInstPtr(aCollection)->ba_element;
-			len = _byteArraySize(aCollection);
-			nInst = __intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars);
-			offs = __OBJS2BYTES__(nInst);
-			cp += offs;
-			len -= offs;
-		    }
-		}
-	    }
-
-	    if (cp != NULL) {
-		f = __FILEVal(fp);
-
-		index1 = __intVal(start);
-		index2 = __intVal(stop);
-		if ((index1 < 1) || (index2 > len) || (index2 < index1)) {
-		    RETURN ( self );
-		}
-		if (index2 > len)
-		    index2 = len;
-
-		len = index2 - index1 + 1;
-
-		__BEGIN_INTERRUPTABLE__
-
-		if (_INST(buffered) == true) {
-		    __WRITING__(f)
-		    cnt = fwrite(cp+index1-1, 1, len, f);
-		} else {
-		    do {
-			cp = __ByteArrayInstPtr(aCollection)->ba_element + offs;
-			cnt = write(fileno(f), cp+offs, len);
-		    } while ((cnt < 0) && (errno == EINTR));
-		}
-
-		__END_INTERRUPTABLE__
-
-		if (cnt == len) {
-		    if (_INST(position) != nil) {
-			_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + len);
-		    }
-		    RETURN ( self );
-		}
-		_INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    }
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-    ^ super nextPutAll:aCollection startingAt:start to:stop
-!
-
-cr
-    "append an end-of-line character (or CRLF if in crlf mode).
-     reimplemented for speed"
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    int len, cnt;
-    OBJ fp;
-    char *cp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(readonly))) {
-	if (_INST(binary) != true) {
-	    f = __FILEVal(fp);
-
-	    if (_INST(useCRLF) == true) {
-		cp = "\r\n"; len = 2;
-	    } else {
-		cp = "\n"; len = 1;
-	    }
-	    __BEGIN_INTERRUPTABLE__
-
-	    if (_INST(buffered) == true) {
-		__WRITING__(f)
-		cnt = fwrite(cp, 1, len, f);
-	    } else {
-		do {
-		    cnt = write(fileno(f), cp, len);
-		} while ((cnt < 0) && (errno == EINTR));
-	    }
-
-	    __END_INTERRUPTABLE__
-
-	    if (cnt == len) {
-		if (_INST(position) != nil) {
-		    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + len);
-		}
-		RETURN ( self );
-	    }
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self writeError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #readonly) ifTrue:[^ self errorReadOnly].
-    self errorBinary
+shutDown
+    "close the stream - added for protocol compatibility with PipeStream.
+     see comment there"
+
+    self closeFile
 ! !
 
 !ExternalStream methodsFor:'line reading/writing'!
@@ -2484,381 +1020,1150 @@
     ^ nil
 ! !
 
-!ExternalStream methodsFor:'testing'!
-
-atEnd
-    "return true, if position is at end"
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    OBJ fp;
-    int c;
-
-    if (_INST(hitEOF) == true) {
-	RETURN (true);
-    }
-    if (_INST(buffered) == false) {
-	RETURN (false);
-    }
-
-    _INST(lastErrorNumber) = nil;
-
-    if ((fp = _INST(filePointer)) != nil) {
-	f = __FILEVal(fp);
-#ifdef OLD
-	RETURN ( feof(f) ? true : false );
-#else
-	__READING__(f)
-
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    c = getc(f);
-	} while ((c < 0) && (errno == EINTR) && (clearerr(f), 1));
-	__END_INTERRUPTABLE__
-
-	if (c != EOF) {
-	    ungetc(c, f);
-	    RETURN (false);
-	}
-	if (ferror(f) && (errno != 0)) {
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	} else {
-	    _INST(hitEOF) = true;
-	    RETURN (true);
-	}
-#endif
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    ^ self errorNotOpen
-!
-
-canReadWithoutBlocking
-    "return true, if any data is available for reading (i.e.
-     a read operation will not block the smalltalk process), false otherwise."
-
-    |fd|
-
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    mode == #writeonly ifTrue:[^ self errorWriteOnly].
-
-    fd := self fileDescriptor.
-    ^ OperatingSystem readCheck:fd
-
-    "
-     |pipe|
-
-     pipe := PipeStream readingFrom:'(sleep 10; echo hello)'.
-     pipe canReadWithoutBlocking ifTrue:[
-	 Transcript showCr:'data available'
-     ] ifFalse:[
-	 Transcript showCr:'no data available'
-     ].
-     pipe close
-    "
-!
-
-canWriteWithoutBlocking
-    "return true, if data can be written into the stream 
-     (i.e. a write operation will not block the smalltalk process)."
+!ExternalStream methodsFor:'misc functions'!
+
+async:aBoolean
+    "set/clear the async attribute - if set the availability of data on 
+     the receiver will trigger an ioInterrupt.
+     If cleared (which is the default) no special notification is made."
 
     |fd|
 
     filePointer isNil ifTrue:[^ self errorNotOpen].
-    mode == #readonly ifTrue:[^ self errorReadOnly].
-
     fd := self fileDescriptor.
-    ^ OperatingSystem writeCheck:fd
-! !
-
-!ExternalStream methodsFor:'waiting for I/O'!
-
-readWait
-    "suspend the current process, until the receiver
-     becomes ready for reading. If data is already available,
-     return immediate. 
-     The other threads are not affected by the wait."
-
-    self readWaitWithTimeoutMs:nil
+    aBoolean ifTrue:[
+	^ OperatingSystem enableIOInterruptsOn:fd
+    ].
+    ^ OperatingSystem disableIOInterruptsOn:fd
 !
 
-readWaitWithTimeout:timeout
-    "suspend the current process, until the receiver
-     becomes ready for reading or a timeout (in seconds) expired. 
-     If data is already available, return immediate. 
-     Return true if a timeout occured (i.e. false, if data is available).
-     The other threads are not affected by the wait."
-
-    ^ self readWaitWithTimeoutMs:timeout * 1000
+backStep
+    "step back one element -
+     redefined, since position is redefined here"
+
+    self position:(self position - 1)
 !
 
-readWaitWithTimeoutMs:timeout 
-    "suspend the current process, until the receiver
-     becomes ready for reading or a timeout (in milliseconds) expired. 
-     If data is already available, return immediate. 
-     Return true if a timeout occured (i.e. false, if data is available).
-     The other threads are not affected by the wait."
-
-    |fd inputSema hasData wasBlocked|
+blocking:aBoolean
+    "set/clear the blocking attribute - if set (which is the default)
+     a read (using next) on the receiver will block until data is available.
+     If cleared, a read operation will immediately return with a value of
+     nil."
 
     filePointer isNil ifTrue:[^ self errorNotOpen].
-    mode == #writeonly ifTrue:[^ self errorWriteOnly].
-
-    fd := self fileDescriptor.
-    (OperatingSystem readCheck:fd) ifTrue:[^ false].
-
-    wasBlocked := OperatingSystem blockInterrupts.
-    hasData := OperatingSystem readCheck:fd.
-    hasData ifFalse:[
-	inputSema := Semaphore new.
-	[
-	    timeout notNil ifTrue:[
-		Processor signal:inputSema afterMilliseconds:timeout 
-	    ].
-	    Processor signal:inputSema onInput:fd.
-	    Processor activeProcess state:#ioWait.
-	    inputSema wait.
-	    Processor disableSemaphore:inputSema.
-	    hasData := OperatingSystem readCheck:fd
-	] valueOnUnwindDo:[
-	    Processor disableSemaphore:inputSema.
-	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-	]
-    ].
-    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-    ^ hasData not
+    ^ OperatingSystem setBlocking:aBoolean on:(self fileDescriptor)
+!
+
+close
+    "close the stream - tell operating system"
+
+    filePointer isNil ifTrue:[^ self].
+    Lobby unregister:self.
+    self closeFile.
+    filePointer := nil
+!
+
+create
+    "create the stream
+     - this must be redefined in subclass"
+
+    ^ self subclassResponsibility
+!
+
+ioctl:ioctlNumber
+    "to provide a simple ioctl facility - an ioctl is performed
+     on the underlying file; no arguments are passed."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    int ret, ioNum, ioArg;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if ((fp = _INST(filePointer)) != nil) {
+	if (__isSmallInteger(ioctlNumber)) {
+	    ioNum = __intVal(ioctlNumber);
+	    f = __FILEVal(fp);
+
+	    __BEGIN_INTERRUPTABLE__
+	    do {
+		ret = ioctl(fileno(f), ioNum);
+	    } while ((ret < 0) && (errno == EINTR));
+	    __END_INTERRUPTABLE__
+
+	    if (ret >= 0) {
+		RETURN ( __MKSMALLINT(ret) );
+	    }
+	    _INST(position) = nil;
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self ioError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    "
+     ioctl-number is not an integer
+    "
+    ^ self primitiveFailed
+!
+
+ioctl:ioctlNumber with:arg
+    "to provide a simple ioctl facility - an ioctl is performed
+     on the underlying file; the argument is passed as argument.
+     If the argument is a number, its directly passed; if its a
+     kind of ByteArray (ByteArray, String or Structure) a pointer to
+     the data is passed. This allows performing most ioctls - however,
+     it might be tricky to setup the buffer."
+
+%{  /* NOCONTEXT */
+    FILE *f;
+    int ret, ioNum;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if ((fp = _INST(filePointer)) != nil) {
+	if (__isSmallInteger(ioctlNumber) 
+	 && (__isSmallInteger(arg) || __isBytes(arg))) {
+	    f = __FILEVal(fp);
+	    ioNum = __intVal(ioctlNumber);
+
+	    __BEGIN_INTERRUPTABLE__
+	    do {
+		if (__isSmallInteger(arg)) {
+		    ret = ioctl(fileno(f), ioNum, __intVal(arg));
+		} else {
+		    ret = ioctl(fileno(f), ioNum, __ByteArrayInstPtr(arg)->ba_element);
+		}
+	    } while ((ret < 0) && (errno == EINTR));
+	    __END_INTERRUPTABLE__
+
+	    if (ret >= 0) {
+		RETURN ( __MKSMALLINT(ret) );
+	    }
+	    _INST(position) = nil;
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self ioError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    "
+     ioctl-number is not an integer or argument is not byteArray-like
+    "
+    ^ self primitiveFailed
+!
+
+open
+    "open the stream
+     - this must be redefined in subclass"
+
+    ^ self subclassResponsibility
+!
+
+position
+    "return the position
+     - this must be redefined in subclass"
+
+    ^ self subclassResponsibility
+!
+
+position:anInteger
+    "set the position
+     - this must be redefined in subclass"
+
+    ^ self subclassResponsibility
+!
+
+reset
+    "set the read position to the beginning of the collection"
+
+    self position:"0" 1
+!
+
+setToEnd
+    "redefined since it must be implemented differently"
+
+    ^ self subclassResponsibility
+! !
+
+!ExternalStream methodsFor:'non homogenous reading'!
+
+nextByte
+    "read the next byte and return it as an Integer; return nil on error.
+     This is allowed in both text and binary modes, always returning the
+     bytes binary value as an integer in 0..255."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    unsigned char byte;
+    int cnt;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	f = __FILEVal(fp);
+
+	if (_INST(buffered) == true) {
+	    __READING__(f)
+	}
+
+	__BEGIN_INTERRUPTABLE__
+	do {
+	    if (_INST(buffered) == false) {
+		cnt = read(fileno(f), &byte, 1);
+	    } else {
+		cnt = fread(&byte, 1, 1, f);
+	    }
+	} while ((cnt < 0) && (errno == EINTR));
+	__END_INTERRUPTABLE__
+
+	if (cnt == 1) {
+	    if (_INST(position) != nil)
+		_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 1);
+	    RETURN ( __MKSMALLINT(byte) );
+	}
+	if (cnt == 0) {
+	    _INST(hitEOF) = true;
+/*
+	    if (errno == EWOULDBLOCK) {
+		RETURN (nil);
+	    }
+*/
+	}
+	_INST(position) = nil;
+	_INST(lastErrorNumber) = __MKSMALLINT(errno);
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    ^ self errorWriteOnly
+!
+
+nextBytes:count into:anObject
+    "read the next count bytes into an object and return the number of
+     bytes read. On EOF, 0 is returned.
+     If the receiver is some socket/pipe-like stream, an exception
+     is raised if the connection is broken.
+
+     The object must have non-pointer indexed instvars (i.e. it must be 
+     a ByteArray, String, Float- or DoubleArray).
+     If anObject is a string or byteArray and reused, this provides the
+     fastest possible physical I/O (since no new objects are allocated).
+
+     Use with care - non object oriented i/o.
+     Warning: in general, you cannot use this method to pass data from other 
+     architectures since it does not care for byte order or float representation."
+
+    ^ self nextBytes:count into:anObject startingAt:1
 !
 
-writeWait
-    "suspend the current process, until the receiver
-     becomes ready for writing.
-     Return immediate if the receiver is already ready. 
-     The other threads are not affected by the wait."
-
-    self writeWaitWithTimeoutMs:nil
+nextBytes:count into:anObject startingAt:start
+    "read the next count bytes into an object and return the number of
+     bytes read or 0 on EOF. 
+     If the receiver is some socket/pipe-like stream, an exception
+     is raised if the connection is broken.
+     Notice, that in contrast to other methods
+     here, this does NOT return nil on EOF, but the actual count.
+     Thus allowing read of partial blocks.
+
+     The object must have non-pointer indexed instvars 
+     (i.e. it must be a ByteArray, String, Float- or DoubleArray).
+     If anObject is a string or byteArray and reused, this provides the
+     fastest possible physical I/O (since no new objects are allocated).
+
+     Use with care - non object oriented I/O.
+     Warning: in general, you cannot use this method to pass data from other 
+     architectures since it does not care for byte order or float representation."
+
+%{
+    FILE *f;
+    int cnt, offs, ret;
+    int objSize, nInstVars, nInstBytes;
+    char *cp;
+    OBJ pos, fp, oClass;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if (__bothSmallInteger(count, start)) {
+	    f = __FILEVal(fp);
+
+	    oClass = __Class(anObject);
+	    switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+		case BYTEARRAY:
+		case WORDARRAY:
+		case LONGARRAY:
+		case FLOATARRAY:
+		case DOUBLEARRAY:
+		    break;
+		default:
+		    goto bad;
+	    }
+	    cnt = __intVal(count);
+	    offs = __intVal(start) - 1;
+	    nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+	    nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
+	    objSize = __Size(anObject) - nInstBytes;
+	    if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
+		/* 
+		 * mhmh - since we are interruptable, anObject may move.
+		 * therefore, fetch the cp-pointer within the loop
+		 */
+		if (_INST(buffered) == true) {
+		    __READING__(f)
+		}
+
+		__BEGIN_INTERRUPTABLE__
+		do {
+		    errno = 0;
+		    /*
+		     * because we are interruptable, refetch pointer
+		     */
+		    cp = (char *)__InstPtr(anObject) + nInstBytes + offs;
+		    if (_INST(buffered) == false) {
+			ret = read(fileno(f), cp, cnt);
+		    } else {
+			if (feof(f)) {
+			    ret = 0;
+			    break;
+			}
+			ret = fread(cp, 1, cnt, f);
+		    }
+		} while ((ret < 0) && (errno == EINTR));
+
+		__END_INTERRUPTABLE__
+		cnt = ret;
+
+		if (cnt > 0) {
+		    pos = _INST(position);
+		    if (pos != nil) {
+			_INST(position) = __MKSMALLINT(__intVal(pos) + cnt);
+		    }
+		    RETURN (__MKSMALLINT(cnt));
+		}
+		if (cnt == 0) { 
+		    _INST(hitEOF) = true;
+		    RETURN (__MKSMALLINT(cnt));
+		}
+
+		_INST(position) = nil;
+		_INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    }
+	}
+    }
+bad: ;
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    "
+     count not integer or arg not bit-like (String, ByteArray etc)
+    "
+    ^ self primitiveFailed
 !
 
-writeWaitWithTimeout:timeout
-    "suspend the current process, until the receiver
-     becomes ready for writing or a timeout (in seconds) expired. 
-     Return true if a timeout occured (i.e. false, if data is available).
-     Return immediate if the receiver is already ready. 
-     The other threads are not affected by the wait."
-
-    ^ self writeWaitWithTimeoutMs:timeout * 1000
+nextBytesInto:anObject
+    "read bytes into an object, regardless of binary/text mode.
+     The number of bytes to read is defined by the objects size.
+     Return the number of bytes read. On EOF, 0 is returned.
+     If the receiver is some socket/pipe-like stream, an exception
+     is raised if the connection is broken.
+
+     The object to read into must have non-pointer indexed instvars 
+     (i.e. it must be a ByteArray, String, Float- or DoubleArray).     
+     If anObject is a string or byteArray and reused, this provides the
+     fastest possible physical I/O (since no new objects are allocated).
+
+     Use with care - non object oriented i/o.
+     Warning: in general, you cannot use this method to pass data from other 
+     architectures since it does not care for byte order or float representation."
+
+    ^ self nextBytes:(anObject size) into:anObject startingAt:1
+
+    " to read 100 bytes from a stream:
+    
+     |b aStream|
+
+     aStream := 'smalltalk.rc' asFilename readStream.
+     b := ByteArray new:100.
+     aStream nextBytesInto:b.
+     aStream close.
+     b inspect
+    "
+
+    "
+     |s aStream|
+     aStream := 'smalltalk.rc' asFilename readStream.
+     s := String new:100.
+     aStream nextBytesInto:s.
+     aStream close.
+     s inspect
+    "
+!
+
+nextLong
+    "Read four bytes (msb-first) and return the value as a 32-bit signed Integer.
+     The returned value may be a LargeInteger.
+     (msb-first for compatibility with other smalltalks)"
+
+    ^ self nextUnsignedLongMSB:true
+!
+
+nextLongMSB:msbFlag
+    "Read four bytes and return the value as a 32-bit signed Integer, 
+     which may be a LargeInteger.
+     If msbFlag is true, value is read with most-significant byte first, 
+     otherwise least-significant byte comes first.
+     A nil is returned, if EOF is hit before all 4 bytes have been read.
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	FILE *f;
+	int first, second, third, fourth;
+	int value;
+
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+	__READING__(f)
+
+	do {
+	    first = getc(f);
+	} while ((first < 0) && (errno == EINTR));
+	if (first != EOF) {
+	    do {
+		second = getc(f);
+	    } while ((second < 0) && (errno == EINTR));
+	    if (second != EOF) {
+		do {
+		    third = getc(f);
+		} while ((third < 0) && (errno == EINTR));
+		if (third != EOF) {
+		    do {
+			fourth = getc(f);
+		    } while ((fourth < 0) && (errno == EINTR));
+		    if (fourth != EOF) {
+			__END_INTERRUPTABLE__
+
+			if (msbFlag == true) {
+			    value = (first & 0xFF);
+			    value = (value<<8) | (second & 0xFF);
+			    value = (value<<8) | (third & 0xFF);
+			    value = (value<<8) | (fourth & 0xFF);
+			} else {
+			    value = (fourth & 0xFF);
+			    value = (value<<8) | (third & 0xFF);
+			    value = (value<<8) | (second & 0xFF);
+			    value = (value<<8) | (first & 0xFF);
+			}
+			if (_INST(position) != nil) {
+			    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 4);
+			}
+			if ((value >= _MIN_INT) && (value <= _MAX_INT)) {
+			    RETURN ( __MKSMALLINT(value));
+			}
+			RETURN ( _MKLARGEINT(value) );
+		    }
+		}
+	    }
+	}
+	__END_INTERRUPTABLE__
+
+	if (ferror(f) && (errno != 0)) {
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    _INST(position) = nil;
+	} else {
+	    _INST(hitEOF) = true;
+	    RETURN (nil);
+	}
+    }
+%}.
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    ^ self readError.
 !
 
-writeWaitWithTimeoutMs:timeout
-    "suspend the current process, until the receiver
-     becomes ready for writing or a timeout (in seconds) expired. 
-     Return true if a timeout occured (i.e. false, if data is available).
-     Return immediate if the receiver is already ready. 
-     The other threads are not affected by the wait."
-
-    |fd outputSema canWrite wasBlocked|
-
-    filePointer isNil ifTrue:[
-	^ self errorNotOpen
-    ].
-    mode == #readonly ifTrue:[
-	^ self errorReadOnly
+nextShortMSB:msbFlag
+    "Read two bytes and return the value as a 16-bit signed Integer.
+     If msbFlag is true, value is read with most-significant byte first, 
+     otherwise least-significant byte comes first.
+     A nil is returned if EOF is reached (also when EOF is hit after the first byte).
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	FILE *f;
+	int first, second, err;
+	short value;
+
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+	__READING__(f)
+
+	do {
+	    first = getc(f);
+	} while ((first < 0) && (errno == EINTR));
+
+	if (first != EOF) {
+	    do {
+		second = getc(f);
+	    } while ((second < 0) && (errno == EINTR));
+
+	    __END_INTERRUPTABLE__
+	    if (second != EOF) {
+		if (_INST(position) != nil) {
+		    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 2);
+		}
+		if (msbFlag == true) {
+		    value = ((first & 0xFF) << 8) | (second & 0xFF);
+		} else {
+		    value = ((second & 0xFF) << 8) | (first & 0xFF);
+		}
+		RETURN (__MKSMALLINT(value));
+	    }
+	}
+	__END_INTERRUPTABLE__
+
+	if (ferror(f) && (errno != 0)) {
+	    _INST(position) = nil;
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	} else {
+	    _INST(hitEOF) = true;
+	    RETURN (nil);
+	}
+    }
+%}.
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    ^ self readError.
+!
+
+nextUnsignedLongMSB:msbFlag
+    "Read four bytes and return the value as a 32-bit unsigned Integer, which may be
+     a LargeInteger.
+     If msbFlag is true, value is read with most-significant byte first, otherwise
+     least-significant byte comes first.
+     A nil is returned, if endOfFile occurs before all 4 bytes have been read.
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	FILE *f;
+	int first, second, third, fourth;
+	unsigned int value;
+
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+	__READING__(f)
+
+	do {
+	    first = getc(f);
+	} while ((first < 0) && (errno == EINTR));
+	if (first != EOF) {
+	    do {
+		second = getc(f);
+	    } while ((second < 0) && (errno == EINTR));
+	    if (second != EOF) {
+		do {
+		    third = getc(f);
+		} while ((third < 0) && (errno == EINTR));
+		if (third != EOF) {
+		    do {
+			fourth = getc(f);
+		    } while ((fourth < 0) && (errno == EINTR));
+		    if (fourth != EOF) {
+			__END_INTERRUPTABLE__
+
+			if (msbFlag == true) {
+			    value = (first & 0xFF);
+			    value = (value<<8) | (second & 0xFF);
+			    value = (value<<8) | (third & 0xFF);
+			    value = (value<<8) | (fourth & 0xFF);
+			} else {
+			    value = (fourth & 0xFF);
+			    value = (value<<8) | (third & 0xFF);
+			    value = (value<<8) | (second & 0xFF);
+			    value = (value<<8) | (first & 0xFF);
+			}
+			if (_INST(position) != nil) {
+			    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 4);
+			}
+			if (value <= _MAX_INT) {
+			    RETURN ( __MKSMALLINT(value));
+			}
+			RETURN ( _MKULARGEINT(value) );
+		    }
+		}
+	    }
+	}
+	__END_INTERRUPTABLE__
+
+	if (ferror(f) && (errno != 0)) {
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    _INST(position) = nil;
+	} else {
+	    _INST(hitEOF) = true;
+	    RETURN (nil);
+	}
+    }
+%}.
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    ^ self readError.
+!
+
+nextUnsignedShortMSB:msbFlag
+    "Read two bytes and return the value as a 16-bit unsigned Integer.
+     If msbFlag is true, value is read with most-significant byte first, otherwise
+     least-significant byte comes first.
+     A nil is returned if EOF is reached (also when EOF is hit after the first byte).
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	FILE *f;
+	int first, second;
+	unsigned value;
+
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+	__READING__(f)
+
+	do {
+	    first = getc(f);
+	} while ((first < 0) && (errno == EINTR));
+
+	if (first != EOF) {
+	    do {
+		second = getc(f);
+	    } while ((second < 0) && (errno == EINTR));
+
+	    __END_INTERRUPTABLE__
+	    if (second != EOF) {
+		if (_INST(position) != nil) {
+		    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 2);
+		}
+		if (msbFlag == true) {
+		    value = ((first & 0xFF) << 8) | (second & 0xFF);
+		} else {
+		    value = ((second & 0xFF) << 8) | (first & 0xFF);
+		}
+		RETURN (__MKSMALLINT(value));
+	    }
+	}
+	__END_INTERRUPTABLE__
+
+	if (ferror(f) && (errno != 0)) {
+	    _INST(position) = nil;
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	} else {
+	    _INST(hitEOF) = true;
+	    RETURN (nil);
+	}
+    }
+%}.
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    ^ self readError.
+!
+
+nextWord
+    "in text-mode:
+	 read the alphaNumeric next word (i.e. up to non letter-or-digit).
+	 return a string containing those characters.
+     in binary-mode:
+	 read two bytes (msb-first) and return the value as a 16-bit 
+	 unsigned Integer (for compatibility with other smalltalks)"
+
+    binary ifTrue:[
+	^ self nextUnsignedShortMSB:true
     ].
-
-    fd := self fileDescriptor.
-    (OperatingSystem writeCheck:fd) ifTrue:[^ false].
-
-    wasBlocked := OperatingSystem blockInterrupts.
-    canWrite := OperatingSystem writeCheck:fd.
-    canWrite ifFalse:[
-	outputSema := Semaphore new.
-	[
-	    timeout notNil ifTrue:[
-		Processor signal:outputSema afterMilliseconds:timeout
-	    ].
-	    Processor signal:outputSema onOutput:fd.
-	    Processor activeProcess state:#ioWait.
-	    outputSema wait.
-	    Processor disableSemaphore:outputSema.
-	    canWrite := OperatingSystem writeCheck:fd
-	] valueOnUnwindDo:[
-	    Processor disableSemaphore:outputSema.
-	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-	]
+    ^ self nextAlphaNumericWord
+! !
+
+!ExternalStream methodsFor:'non homogenous writing'!
+
+nextPutByte:aByteValue
+    "write a byte.
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    char c;
+    OBJ pos, fp;
+    int cnt;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))) {
+	if (__isSmallInteger(aByteValue)) {
+	    c = __intVal(aByteValue);
+	    f = __FILEVal(fp);
+	    __BEGIN_INTERRUPTABLE__
+/*
+ *#ifdef OLD
+ *          if (_INST(buffered) == false) {
+ *              cnt = write(fileno(f), &c, 1);
+ *          } else 
+ *#endif
+ *          {
+ *              __WRITING__(f)
+ *              cnt = fwrite(&c, 1, 1, f);
+ *#ifndef OLD
+ *              if (_INST(buffered) == false) {
+ *                  fflush(f);
+ *              }
+ *#endif
+ *          }
+ */
+	    if (_INST(buffered) == true) {
+		__WRITING__(f)
+		cnt = fwrite(&c, 1, 1, f);
+	    } else {
+		do {
+		    cnt = write(fileno(f), &c, 1);
+		} while ((cnt < 0) && (errno == EINTR));
+	    }
+	    __END_INTERRUPTABLE__
+
+	    if (cnt == 1) {
+		pos = _INST(position);
+		if (pos != nil)
+		    _INST(position) = __MKSMALLINT(__intVal(pos) + 1);
+		RETURN (self);
+	    }
+	    if (cnt < 0) {
+		_INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    }
+	}
+    }
+%}.
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+    ^ self writeError.
+!
+
+nextPutBytes:count from:anObject
+    "write count bytes from an object.
+     Return the number of bytes written or nil on error.
+     The object must have non-pointer indexed instvars 
+     (i.e. be a ByteArray, String, Float- or DoubleArray).     
+     Use with care - non object oriented i/o.
+     Warning: in general, you cannot use this method to pass data to other 
+     architectures since it does not care for byte order or float representation."
+
+    ^ self nextPutBytes:count from:anObject startingAt:1
+!
+
+nextPutBytes:count from:anObject startingAt:start
+    "write count bytes from an object starting at index start.
+     return the number of bytes written - which could be 0.
+     The object must have non-pointer indexed instvars 
+     (i.e. be a ByteArray, String, Float- or DoubleArray).     
+     Use with care - non object oriented i/o.
+     Warning: in general, you cannot use this method to pass data to other 
+     architectures since it does not care for byte order or float representation."
+
+%{  /* NOCONTEXT */
+    FILE *f;
+    int cnt, offs;
+    int objSize, nInstVars, nInstBytes;
+    char *cp;
+    OBJ oClass, pos, fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))) {
+	if (__bothSmallInteger(count, start)) {
+	    oClass = __Class(anObject);
+	    switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+		case BYTEARRAY:
+		case WORDARRAY:
+		case LONGARRAY:
+		case FLOATARRAY:
+		case DOUBLEARRAY:
+		    break;
+		default:
+		    goto bad;
+	    }
+	    cnt = __intVal(count);
+	    offs = __intVal(start) - 1;
+	    f = __FILEVal(fp);
+
+	    nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+	    nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
+	    objSize = __Size(anObject) - nInstBytes;
+	    if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) {
+		cp = (char *)__InstPtr(anObject) + nInstBytes + offs;
+		__BEGIN_INTERRUPTABLE__
+
+		if (_INST(buffered) == true) {
+		    __WRITING__(f)
+		    cnt = fwrite(cp, 1, cnt, f);
+		} else {
+		    do {
+			cp = (char *)__InstPtr(anObject) + nInstBytes + offs;
+			cnt = write(fileno(f), cp, cnt);
+		    } while ((cnt < 0) && (errno == EINTR));
+		}
+
+		__END_INTERRUPTABLE__
+
+		if (cnt >= 0) {
+		    pos = _INST(position);
+		    if (pos != nil)
+			_INST(position) = __MKSMALLINT(__intVal(pos) + cnt);
+		    RETURN ( __MKSMALLINT(cnt) );
+		}
+		_INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    }
+	}
+    }
+bad: ;
+%}.
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+    ^ self primitiveFailed
+!
+
+nextPutBytesFrom:anObject
+    "write bytes from an object; the number of bytes is defined by
+     the objects size.
+     Return the number of bytes written or nil on error.
+     The object must have non-pointer indexed instvars 
+     (i.e. be a ByteArray, String, Float- or DoubleArray).     
+     Use with care - non object oriented i/o.
+     Warning: in general, you cannot use this method to pass data to other 
+     architectures since it does not care for byte order or float representation."
+
+    ^ self nextPutBytes:(anObject size) from:anObject startingAt:1
+!
+
+nextPutLong:aNumber MSB:msbFlag
+    "Write the argument, aNumber as a long (four bytes). If msbFlag is
+     true, data is written most-significant byte first; otherwise least
+     first.
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+
+    int num;
+    char bytes[4];
+    FILE *f;
+    int cnt;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))
+     && __isSmallInteger(aNumber)) {
+	num = __intVal(aNumber);
+	if (msbFlag == true) {
+	    bytes[0] = (num >> 24) & 0xFF;
+	    bytes[1] = (num >> 16) & 0xFF;
+	    bytes[2] = (num >> 8) & 0xFF;
+	    bytes[3] = num & 0xFF;
+	} else {
+	    bytes[3] = (num >> 24) & 0xFF;
+	    bytes[2] = (num >> 16) & 0xFF;
+	    bytes[1] = (num >> 8) & 0xFF;
+	    bytes[0] = num & 0xFF;
+	}
+
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+
+	if (_INST(buffered) == true) {
+	    __WRITING__(f)
+	    cnt = fwrite(bytes, 1, 4, f);
+	} else {
+	    do {
+		cnt = write(fileno(f), bytes, 4);
+	    } while ((cnt < 0) && (errno == EINTR));
+	}
+
+	__END_INTERRUPTABLE__
+
+	if (cnt == 4) {
+	    if (_INST(position) != nil) {
+		_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 4);
+	    }
+	    RETURN ( self );
+	}
+	_INST(lastErrorNumber) = __MKSMALLINT(errno);
+    }
+%}.
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+
+    aNumber isInteger ifTrue:[
+	msbFlag ifTrue:[
+	    "high word first"
+	    (self nextShortPut:(aNumber // 16r10000) MSB:true) isNil ifTrue:[^ nil].
+	    ^ self nextShortPut:(aNumber \\ 16r10000) MSB:true
+	].
+	"low word first"
+	(self nextShortPut:(aNumber \\ 16r10000) MSB:false) isNil ifTrue:[^ nil].
+	^ self nextShortPut:(aNumber // 16r10000) MSB:false.
     ].
-    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-    ^ canWrite not
+    self argumentMustBeInteger
+!
+
+nextPutShort:aNumber MSB:msbFlag
+    "Write the argument, aNumber as a short (two bytes). If msbFlag is
+     true, data is written most-significant byte first; otherwise least
+     first.
+     Works in both binary and text modes."
+
+%{  /* NOCONTEXT */
+
+    int num;
+    char bytes[2];
+    FILE *f;
+    int cnt;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))
+     && __isSmallInteger(aNumber)) {
+	num = __intVal(aNumber);
+	if (msbFlag == true) {
+	    bytes[0] = (num >> 8) & 0xFF;
+	    bytes[1] = num & 0xFF;
+	} else {
+	    bytes[1] = (num >> 8) & 0xFF;
+	    bytes[0] = num & 0xFF;
+	}
+
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+
+	if (_INST(buffered) == true) {
+	    __WRITING__(f)
+	    cnt = fwrite(bytes, 1, 2, f);
+	} else {
+	    do {
+		cnt = write(fileno(f), bytes, 2);
+	    } while ((cnt < 0) && (errno == EINTR));
+	}
+
+	__END_INTERRUPTABLE__
+
+	if (cnt == 2) {
+	    if (_INST(position) != nil) {
+		_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + 2);
+	    }
+	    RETURN ( self );
+	}
+	_INST(lastErrorNumber) = __MKSMALLINT(errno);
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+    self argumentMustBeInteger
 ! !
-     
-!ExternalStream methodsFor:'reimplemented for speed'!
-
-peekFor:anObject
-    "return true and move past next element, if next == something.
-     Otherwise, stay and return false. False is also returned
-     when EOF is encountered.
-     The argument must be an integer if in binary, a character if in
-     text mode; only single byte characters are currently supported."
+
+!ExternalStream methodsFor:'private'!
+
+clearEOF
+    hitEOF := false
+!
+
+reOpen
+    "sent after snapin to reopen streams.
+     cannot reopen here since I am abstract and have no device knowledge"
+
+    self class name errorPrint. ': cannot reOpen stream - stream closed' errorPrintNL.
+    filePointer := nil.
+    Lobby unregister:self.
+!
+
+setLastError:aNumber
+    lastErrorNumber := aNumber
+! !
+
+!ExternalStream methodsFor:'queries'!
+
+isBinary
+    "return true, if the stream is in binary (as opposed to text-) mode.
+     The default when created is false."
+
+    ^ binary
+!
+
+isExternalStream
+    "return true, if the receiver is some kind of externalStream;
+     true is returned here - the method redefined from Object."
+
+    ^ true
+!
+
+isReadable 
+    "return true, if this stream can be read from"
+
+    ^ (mode ~~ #writeonly)
+!
+
+isWritable 
+    "return true, if this stream can be written to"
+
+    ^ (mode ~~ #readonly)
+! !
+
+!ExternalStream methodsFor:'reading'!
+
+next
+    "return the next element; advance read position.
+     In binary mode, an integer is returned, otherwise a character.
+     If there are no more elements, nil is returned."
 
 %{  /* NOCONTEXT */
 
     FILE *f;
     int c;
-    int peekValue;
+    OBJ pos, fp;
+    unsigned char ch;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	f = __FILEVal(fp);
+	__BEGIN_INTERRUPTABLE__
+
+	if (_INST(buffered) == true) {
+	    __READING__(f)
+	}
+
+	do {
+	    errno = 0;
+	    if (_INST(buffered) == false) {
+		if (read(fileno(f), &ch, 1) != 1)
+		    c = EOF;
+		else
+		    c = ch;
+	    } else 
+	    {
+		c = getc(f);
+	    }
+	} while ((c < 0) && (errno == EINTR));
+
+	__END_INTERRUPTABLE__
+
+	if (c != EOF) {
+	    pos = _INST(position);
+	    if (__isSmallInteger(pos)) {
+		_INST(position) = __MKSMALLINT(__intVal(pos) + 1);
+	    } else {
+		_INST(position) = nil;
+	    }
+	    if (_INST(binary) == true) {
+		RETURN ( __MKSMALLINT(c & 0xFF) );
+	    }
+	    RETURN ( _MKCHARACTER(c & 0xFF) );
+	}
+/*
+	if (errno == EWOULDBLOCK) {
+	    _INST(hitEOF) = true;
+	    RETURN(nil);
+	}
+*/
+	_INST(position) = nil;
+        
+	if ((_INST(buffered) == false)
+	 || (ferror(f) && (errno != 0))) {
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	} else {
+	    _INST(hitEOF) = true;
+	    RETURN ( nil );
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    self errorWriteOnly
+!
+
+next:count
+    "return the next count elements of the stream as a collection.
+     Redefined to return a String or ByteArray instead of the default: Array."
+
+    |coll|
+
+    binary ifTrue:[
+	coll := ByteArray uninitializedNew:count
+    ] ifFalse:[
+	coll := String new:count
+    ].
+    "/
+    "/ Q: should we use: 
+    "/    self nextBytes:count into:coll startingAt:1
+    "/
+    1 to:count do: [:index |
+	coll at:index put:(self next)
+    ].
+    ^ coll
+!
+
+peek
+    "return the element to be read next without advancing read position.
+     In binary mode, an integer is returned, otherwise a character.
+     If there are no more elements, nil is returned.
+     Not allowed in unbuffered mode."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    REGISTER int c;
     OBJ fp;
 
     _INST(lastErrorNumber) = nil;
     if (((fp = _INST(filePointer)) != nil)
      && (_INST(mode) != @symbol(writeonly))) {
-	if (_INST(binary) == true) {
-	    if (__isSmallInteger(anObject)) {
-		peekValue = __intVal(anObject) & 0xFF;
-	    } else {
-		goto bad;
-	    }
-	} else {
-	    if (__isCharacter(anObject)) {
-		peekValue = __intVal(_characterVal(anObject)) & 0xFF;
-	    } else {
-		goto bad;
-	    }
-	}
-
-	f = __FILEVal(fp);
-
-	if (feof(f)) {
-	    _INST(hitEOF) = true;
-	    RETURN (false);
-	}
-
-	__READING__(f)
-
-	errno = 0;
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    if (feof(f)) {
-		break;
-	    }
-	    c = getc(f);
-	} while ((c < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
-
-	if (feof(f)) {
-	    _INST(hitEOF) = true;
-	}
-
-	if (c == peekValue) {
-	    OBJ pos;
-
-	    if ((pos = _INST(position)) != nil) {
-		_INST(position) = __MKSMALLINT(__intVal(pos) + 1);
-	    }
-	    RETURN (true);
-	}
-
-	if (c != EOF) {
-	    ungetc(c, f);
-	    RETURN (false);
-	}
-
-	_INST(hitEOF) = true;
-	if (ferror(f) && (errno != 0)) {
-	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-	} else {
-	    RETURN (false);
-	}
-    }
-bad: ;
-%}.
-    mode == #writeonly ifTrue:[^ self errorWriteOnly].
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    ^ super peekFor:anObject
-!
-
-nextMatchFor:anObject
-    "skip all objects up-to and including anObject, return anObject on success,
-     nil if end-of-file is reached before. The next read operation will return
-     the element after anObject.
-     Only single byte characters are currently supported."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    int peekValue, c;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	if ((_INST(binary) == true) && __isSmallInteger(anObject)) {
-	    peekValue = __intVal(anObject) & 0xFF;
-	} else {
-	    if ((_INST(binary) != true) && __isCharacter(anObject)) {
-		peekValue = __intVal(_characterVal(anObject)) & 0xFF;
-	    } else {
-		peekValue = -1;
-	    }   
-	}
-
-	if (peekValue >= 0) {
-	    _INST(position) = nil;
+#ifdef OLD
+	if (_INST(buffered) == true) 
+#endif
+	{
 	    f = __FILEVal(fp);
+
 	    __BEGIN_INTERRUPTABLE__
 	    __READING__(f)
 
-	    for (;;) {
-		do {
-		    c = getc(f);
-		} while ((c < 0) && (errno == EINTR));
-                
-		if (c == EOF) {
-		    __END_INTERRUPTABLE__
-		    if (ferror(f) && (errno != 0)) {
-			_INST(lastErrorNumber) = __MKSMALLINT(errno);
-			break;
-		    }
-		    _INST(hitEOF) = true;
-		    RETURN (nil);
+	    do {
+		c = getc(f);
+	    } while ((c < 0) && (errno == EINTR));
+	    __END_INTERRUPTABLE__
+
+	    if (c != EOF) {
+		ungetc(c, f);
+		if (_INST(binary) == true) {
+		    RETURN ( __MKSMALLINT(c & 0xFF) );
 		}
-		if (c == peekValue) {
-		    __END_INTERRUPTABLE__
-		    RETURN (anObject);
-		}
+		RETURN ( _MKCHARACTER(c & 0xFF) );
 	    }
-	}
-    }
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    ^ super nextMatchFor:anObject
-!
-
-skipLine
-    "read the next line (characters up to newline) skip only;
-     return nil if EOF reached, self otherwise. 
-     Not allowed in binary mode."
-
-%{  /* STACK:2000 */
-
-    FILE *f;
-    char buffer[1024];
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	if (_INST(binary) != true) {
-	    f = __FILEVal(fp);
-            
-	    __READING__(f)
-
-	    __BEGIN_INTERRUPTABLE__
-	    if (fgets(buffer, sizeof(buffer)-1, f) != NULL) {
-		__END_INTERRUPTABLE__
-		RETURN ( self );
-	    }
-	    __END_INTERRUPTABLE__
-
 	    if (ferror(f) && (errno != 0)) {
 		_INST(lastErrorNumber) = __MKSMALLINT(errno);
 	    } else {
@@ -2870,285 +2175,11 @@
 %}.
     lastErrorNumber notNil ifTrue:[^ self readError].
     filePointer isNil ifTrue:[^ self errorNotOpen].
-    binary ifTrue:[^ self errorBinary].
+    buffered ifFalse:[^ self errorNotBuffered].
     ^ self errorWriteOnly
-!
-
-skipThroughAll:aString
-    "search & skip for the sequence given by the argument, aCollection;
-     return nil if not found, self otherwise. If successfull, the next read 
-     will return the character after the searchstring."
-
-    |buffer len first|
-
-    (aString isString and:[binary not]) ifTrue:[
-	len := aString size.
-	first := aString at:1.
-	buffer := String new:len.
-	buffer at:1 put:first.
-	len := len - 1.
-	[true] whileTrue:[
-	    (self skipThrough:first) isNil ifTrue:[
-		^ nil.
-	    ].
-	    (self nextBytes:len into:buffer startingAt:2) == len ifFalse:[
-		^ nil
-	    ].
-	    buffer = aString ifTrue:[
-		"
-		 position back, before string
-		"
-		^ self
-	    ].
-	].
-	"NOT REACHED"
-    ].
-    ^ super skipThroughAll:aString
-
-    "
-     |s|
-     s := 'Makefile' asFilename readStream.
-     s skipThroughAll:'are'.
-     s next:10
-    "
-!
-
-skipToAll:aString
-    "skip for the sequence given by the argument, aCollection;
-     return nil if not found, self otherwise. On a successful match, next read
-     will return characters of aString."
-
-    |oldPos|
-
-    oldPos := self position.
-    (self skipThroughAll:aString) isNil ifTrue:[
-	"
-	 restore position
-	"
-	self position:oldPos.
-	^ nil
-    ].
-    "
-     position before match-string
-    "
-    self position:(self position - aString size).
-    ^ self
-
-    "
-     |s|
-     s := 'Makefile' asFilename readStream.
-     s skipToAll:'are'.
-     s next:10
-    "
-!
-
-skipThrough:aCharacter
-    "skip all characters up-to and including aCharacter. Return the receiver if
-     skip was successfull, otherwise (i.e. if not found) return nil.
-     The next read operation will return the character after aCharacter.
-     The argument, aCharacter must be character, or integer when in binary mode.
-     Only single byte characters are currently supported."
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    REGISTER int c, cSearch;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	if (_INST(binary) == true) {
-	    /* searched for object must be a smallInteger */
-	    if (! __isSmallInteger(aCharacter)) goto badArgument;
-	    cSearch = __intVal(aCharacter);
-	} else {
-	    /* searched for object must be a character */
-	    if (! __isCharacter(aCharacter)) goto badArgument;
-	    cSearch = __intVal(_characterVal(aCharacter));
-	}
-	/* Q: should we just say: "not found" ? */
-	if ((cSearch < 0) || (cSearch > 255)) goto badArgument;
-
-	f = __FILEVal(fp);
-	__READING__(f)
-
-	__BEGIN_INTERRUPTABLE__
-	while (1) {
-#ifdef NOTNEEDED
-	    if (feof(f)) {
-		__END_INTERRUPTABLE__
-		RETURN ( nil );
-	    }
-#endif
-	    do {
-		c = getc(f);
-	    } while ((c < 0) && (errno == EINTR));
-
-	    if (c == cSearch) {
-		__END_INTERRUPTABLE__
-		RETURN (self);
-	    }
-	    if (c < 0) {
-		__END_INTERRUPTABLE__
-		if (ferror(f) && (errno != 0)) {
-		    _INST(lastErrorNumber) = __MKSMALLINT(errno);
-		    break;
-		} else {
-		    _INST(hitEOF) = true;
-		    RETURN (nil);
-		}
-	    }
-	}
-    }
-badArgument: ;
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    "
-     argument must be integer/character in binary mode, 
-     character in text mode
-    "
-    ^ self error:'invalid argument'.
-
-    "
-     |s|
-     s := 'Makefile' asFilename readStream.
-     s skipThrough:$=.
-     s next:10
-    "
-!
-
-skipSeparators
-    "skip all whitespace; next will return next non-white-space character
-     or nil if endOfFile reached. Not allowed in binary mode.
-     - reimplemented for speed"
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    REGISTER int c;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	if (_INST(binary) != true) {
-	    f = __FILEVal(fp);
-            
-	    if (feof(f)) {
-		_INST(hitEOF) = true;
-		RETURN ( nil );
-	    }
-
-	    __READING__(f)
-
-	    __BEGIN_INTERRUPTABLE__
-	    while (1) {
-		do {
-		    if (feof(f)) {
-			__END_INTERRUPTABLE__
-			_INST(hitEOF) = true;
-			RETURN ( nil );
-		    }
-		    c = getc(f);
-		} while ((c < 0) && (errno == EINTR));
-
-		switch (c) {
-		    case ' ':
-		    case '\t':
-		    case '\n':
-		    case '\r':
-		    case '\b':
-		    case '\014':
-			break;
-
-		    default:
-			__END_INTERRUPTABLE__
-			if (c < 0) {
-			    _INST(hitEOF) = true;
-			    if (ferror(f) && (errno != 0)) {
-				_INST(lastErrorNumber) = __MKSMALLINT(errno);
-				goto err;
-			    }
-			    RETURN ( nil );
-			}
-			ungetc(c, f);
-			RETURN ( _MKCHARACTER(c & 0xFF) );
-		}
-	    }
-	}
-    }
-err: ;
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    ^ self errorBinary.
-!
-
-skipSeparatorsExceptCR
-    "skip all whitespace but no newlines;
-     next will return next non-white-space character
-     or nil if endOfFile reached. Not allowed in binary mode.
-     - reimplemented for speed"
-
-%{  /* NOCONTEXT */
-
-    FILE *f;
-    int c;
-    OBJ fp;
-
-    _INST(lastErrorNumber) = nil;
-    if (((fp = _INST(filePointer)) != nil)
-     && (_INST(mode) != @symbol(writeonly))) {
-	if (_INST(binary) != true) {
-	    f = __FILEVal(fp);
-	    __READING__(f)
-
-	    __BEGIN_INTERRUPTABLE__
-	    while (1) {
-                
-		if (feof(f)) {
-		    __END_INTERRUPTABLE__
-		    _INST(hitEOF) = true;
-		    RETURN ( nil );
-		}
-
-		do {
-		    c = getc(f);
-		} while ((c < 0) && (errno == EINTR));
-
-		switch (c) {
-		    case ' ':
-		    case '\t':
-		    case '\b':
-			break;
-
-		    default:
-			__END_INTERRUPTABLE__
-			if (c < 0) {
-			    if (ferror(f) && (errno != 0)) {
-				_INST(lastErrorNumber) = __MKSMALLINT(errno);
-				goto err;
-			    }
-			    _INST(hitEOF) = true;
-			    RETURN ( nil );
-			}
-			ungetc(c, f);
-			RETURN ( _MKCHARACTER(c & 0xFF) );
-		}
-	    }
-	}
-    }
-err: ;
-%}.
-    lastErrorNumber notNil ifTrue:[^ self readError].
-    filePointer isNil ifTrue:[^ self errorNotOpen].
-    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
-    ^ self errorBinary
-!
+! !
+
+!ExternalStream methodsFor:'reimplemented for speed'!
 
 nextAlphaNumericWord
     "read the next word (i.e. up to non letter-or-digit) after first
@@ -3436,4 +2467,974 @@
 	]
     ].
     ^ retVal
+!
+
+nextMatchFor:anObject
+    "skip all objects up-to and including anObject, return anObject on success,
+     nil if end-of-file is reached before. The next read operation will return
+     the element after anObject.
+     Only single byte characters are currently supported."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    int peekValue, c;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if ((_INST(binary) == true) && __isSmallInteger(anObject)) {
+	    peekValue = __intVal(anObject) & 0xFF;
+	} else {
+	    if ((_INST(binary) != true) && __isCharacter(anObject)) {
+		peekValue = __intVal(_characterVal(anObject)) & 0xFF;
+	    } else {
+		peekValue = -1;
+	    }   
+	}
+
+	if (peekValue >= 0) {
+	    _INST(position) = nil;
+	    f = __FILEVal(fp);
+	    __BEGIN_INTERRUPTABLE__
+	    __READING__(f)
+
+	    for (;;) {
+		do {
+		    c = getc(f);
+		} while ((c < 0) && (errno == EINTR));
+                
+		if (c == EOF) {
+		    __END_INTERRUPTABLE__
+		    if (ferror(f) && (errno != 0)) {
+			_INST(lastErrorNumber) = __MKSMALLINT(errno);
+			break;
+		    }
+		    _INST(hitEOF) = true;
+		    RETURN (nil);
+		}
+		if (c == peekValue) {
+		    __END_INTERRUPTABLE__
+		    RETURN (anObject);
+		}
+	    }
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    ^ super nextMatchFor:anObject
+!
+
+peekFor:anObject
+    "return true and move past next element, if next == something.
+     Otherwise, stay and return false. False is also returned
+     when EOF is encountered.
+     The argument must be an integer if in binary, a character if in
+     text mode; only single byte characters are currently supported."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    int c;
+    int peekValue;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if (_INST(binary) == true) {
+	    if (__isSmallInteger(anObject)) {
+		peekValue = __intVal(anObject) & 0xFF;
+	    } else {
+		goto bad;
+	    }
+	} else {
+	    if (__isCharacter(anObject)) {
+		peekValue = __intVal(_characterVal(anObject)) & 0xFF;
+	    } else {
+		goto bad;
+	    }
+	}
+
+	f = __FILEVal(fp);
+
+	if (feof(f)) {
+	    _INST(hitEOF) = true;
+	    RETURN (false);
+	}
+
+	__READING__(f)
+
+	errno = 0;
+	__BEGIN_INTERRUPTABLE__
+	do {
+	    if (feof(f)) {
+		break;
+	    }
+	    c = getc(f);
+	} while ((c < 0) && (errno == EINTR));
+	__END_INTERRUPTABLE__
+
+	if (feof(f)) {
+	    _INST(hitEOF) = true;
+	}
+
+	if (c == peekValue) {
+	    OBJ pos;
+
+	    if ((pos = _INST(position)) != nil) {
+		_INST(position) = __MKSMALLINT(__intVal(pos) + 1);
+	    }
+	    RETURN (true);
+	}
+
+	if (c != EOF) {
+	    ungetc(c, f);
+	    RETURN (false);
+	}
+
+	_INST(hitEOF) = true;
+	if (ferror(f) && (errno != 0)) {
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	} else {
+	    RETURN (false);
+	}
+    }
+bad: ;
+%}.
+    mode == #writeonly ifTrue:[^ self errorWriteOnly].
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    ^ super peekFor:anObject
+!
+
+skipLine
+    "read the next line (characters up to newline) skip only;
+     return nil if EOF reached, self otherwise. 
+     Not allowed in binary mode."
+
+%{  /* STACK:2000 */
+
+    FILE *f;
+    char buffer[1024];
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if (_INST(binary) != true) {
+	    f = __FILEVal(fp);
+            
+	    __READING__(f)
+
+	    __BEGIN_INTERRUPTABLE__
+	    if (fgets(buffer, sizeof(buffer)-1, f) != NULL) {
+		__END_INTERRUPTABLE__
+		RETURN ( self );
+	    }
+	    __END_INTERRUPTABLE__
+
+	    if (ferror(f) && (errno != 0)) {
+		_INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    } else {
+		_INST(hitEOF) = true;
+		RETURN ( nil );
+	    }
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    binary ifTrue:[^ self errorBinary].
+    ^ self errorWriteOnly
+!
+
+skipSeparators
+    "skip all whitespace; next will return next non-white-space character
+     or nil if endOfFile reached. Not allowed in binary mode.
+     - reimplemented for speed"
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    REGISTER int c;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if (_INST(binary) != true) {
+	    f = __FILEVal(fp);
+            
+	    if (feof(f)) {
+		_INST(hitEOF) = true;
+		RETURN ( nil );
+	    }
+
+	    __READING__(f)
+
+	    __BEGIN_INTERRUPTABLE__
+	    while (1) {
+		do {
+		    if (feof(f)) {
+			__END_INTERRUPTABLE__
+			_INST(hitEOF) = true;
+			RETURN ( nil );
+		    }
+		    c = getc(f);
+		} while ((c < 0) && (errno == EINTR));
+
+		switch (c) {
+		    case ' ':
+		    case '\t':
+		    case '\n':
+		    case '\r':
+		    case '\b':
+		    case '\014':
+			break;
+
+		    default:
+			__END_INTERRUPTABLE__
+			if (c < 0) {
+			    _INST(hitEOF) = true;
+			    if (ferror(f) && (errno != 0)) {
+				_INST(lastErrorNumber) = __MKSMALLINT(errno);
+				goto err;
+			    }
+			    RETURN ( nil );
+			}
+			ungetc(c, f);
+			RETURN ( _MKCHARACTER(c & 0xFF) );
+		}
+	    }
+	}
+    }
+err: ;
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    ^ self errorBinary.
+!
+
+skipSeparatorsExceptCR
+    "skip all whitespace but no newlines;
+     next will return next non-white-space character
+     or nil if endOfFile reached. Not allowed in binary mode.
+     - reimplemented for speed"
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    int c;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if (_INST(binary) != true) {
+	    f = __FILEVal(fp);
+	    __READING__(f)
+
+	    __BEGIN_INTERRUPTABLE__
+	    while (1) {
+                
+		if (feof(f)) {
+		    __END_INTERRUPTABLE__
+		    _INST(hitEOF) = true;
+		    RETURN ( nil );
+		}
+
+		do {
+		    c = getc(f);
+		} while ((c < 0) && (errno == EINTR));
+
+		switch (c) {
+		    case ' ':
+		    case '\t':
+		    case '\b':
+			break;
+
+		    default:
+			__END_INTERRUPTABLE__
+			if (c < 0) {
+			    if (ferror(f) && (errno != 0)) {
+				_INST(lastErrorNumber) = __MKSMALLINT(errno);
+				goto err;
+			    }
+			    _INST(hitEOF) = true;
+			    RETURN ( nil );
+			}
+			ungetc(c, f);
+			RETURN ( _MKCHARACTER(c & 0xFF) );
+		}
+	    }
+	}
+    }
+err: ;
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    ^ self errorBinary
+!
+
+skipThrough:aCharacter
+    "skip all characters up-to and including aCharacter. Return the receiver if
+     skip was successfull, otherwise (i.e. if not found) return nil.
+     The next read operation will return the character after aCharacter.
+     The argument, aCharacter must be character, or integer when in binary mode.
+     Only single byte characters are currently supported."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    REGISTER int c, cSearch;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(writeonly))) {
+	if (_INST(binary) == true) {
+	    /* searched for object must be a smallInteger */
+	    if (! __isSmallInteger(aCharacter)) goto badArgument;
+	    cSearch = __intVal(aCharacter);
+	} else {
+	    /* searched for object must be a character */
+	    if (! __isCharacter(aCharacter)) goto badArgument;
+	    cSearch = __intVal(_characterVal(aCharacter));
+	}
+	/* Q: should we just say: "not found" ? */
+	if ((cSearch < 0) || (cSearch > 255)) goto badArgument;
+
+	f = __FILEVal(fp);
+	__READING__(f)
+
+	__BEGIN_INTERRUPTABLE__
+	while (1) {
+#ifdef NOTNEEDED
+	    if (feof(f)) {
+		__END_INTERRUPTABLE__
+		RETURN ( nil );
+	    }
+#endif
+	    do {
+		c = getc(f);
+	    } while ((c < 0) && (errno == EINTR));
+
+	    if (c == cSearch) {
+		__END_INTERRUPTABLE__
+		RETURN (self);
+	    }
+	    if (c < 0) {
+		__END_INTERRUPTABLE__
+		if (ferror(f) && (errno != 0)) {
+		    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+		    break;
+		} else {
+		    _INST(hitEOF) = true;
+		    RETURN (nil);
+		}
+	    }
+	}
+    }
+badArgument: ;
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
+    "
+     argument must be integer/character in binary mode, 
+     character in text mode
+    "
+    ^ self error:'invalid argument'.
+
+    "
+     |s|
+     s := 'Makefile' asFilename readStream.
+     s skipThrough:$=.
+     s next:10
+    "
+!
+
+skipThroughAll:aString
+    "search & skip for the sequence given by the argument, aCollection;
+     return nil if not found, self otherwise. If successfull, the next read 
+     will return the character after the searchstring."
+
+    |buffer len first|
+
+    (aString isString and:[binary not]) ifTrue:[
+	len := aString size.
+	first := aString at:1.
+	buffer := String new:len.
+	buffer at:1 put:first.
+	len := len - 1.
+	[true] whileTrue:[
+	    (self skipThrough:first) isNil ifTrue:[
+		^ nil.
+	    ].
+	    (self nextBytes:len into:buffer startingAt:2) == len ifFalse:[
+		^ nil
+	    ].
+	    buffer = aString ifTrue:[
+		"
+		 position back, before string
+		"
+		^ self
+	    ].
+	].
+	"NOT REACHED"
+    ].
+    ^ super skipThroughAll:aString
+
+    "
+     |s|
+     s := 'Makefile' asFilename readStream.
+     s skipThroughAll:'are'.
+     s next:10
+    "
+!
+
+skipToAll:aString
+    "skip for the sequence given by the argument, aCollection;
+     return nil if not found, self otherwise. On a successful match, next read
+     will return characters of aString."
+
+    |oldPos|
+
+    oldPos := self position.
+    (self skipThroughAll:aString) isNil ifTrue:[
+	"
+	 restore position
+	"
+	self position:oldPos.
+	^ nil
+    ].
+    "
+     position before match-string
+    "
+    self position:(self position - aString size).
+    ^ self
+
+    "
+     |s|
+     s := 'Makefile' asFilename readStream.
+     s skipToAll:'are'.
+     s next:10
+    "
 ! !
+
+!ExternalStream methodsFor:'testing'!
+
+atEnd
+    "return true, if position is at end"
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    OBJ fp;
+    int c;
+
+    if (_INST(hitEOF) == true) {
+	RETURN (true);
+    }
+    if (_INST(buffered) == false) {
+	RETURN (false);
+    }
+
+    _INST(lastErrorNumber) = nil;
+
+    if ((fp = _INST(filePointer)) != nil) {
+	f = __FILEVal(fp);
+#ifdef OLD
+	RETURN ( feof(f) ? true : false );
+#else
+	__READING__(f)
+
+	__BEGIN_INTERRUPTABLE__
+	do {
+	    c = getc(f);
+	} while ((c < 0) && (errno == EINTR) && (clearerr(f), 1));
+	__END_INTERRUPTABLE__
+
+	if (c != EOF) {
+	    ungetc(c, f);
+	    RETURN (false);
+	}
+	if (ferror(f) && (errno != 0)) {
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	} else {
+	    _INST(hitEOF) = true;
+	    RETURN (true);
+	}
+#endif
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self readError].
+    ^ self errorNotOpen
+!
+
+canReadWithoutBlocking
+    "return true, if any data is available for reading (i.e.
+     a read operation will not block the smalltalk process), false otherwise."
+
+    |fd|
+
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    mode == #writeonly ifTrue:[^ self errorWriteOnly].
+
+    fd := self fileDescriptor.
+    ^ OperatingSystem readCheck:fd
+
+    "
+     |pipe|
+
+     pipe := PipeStream readingFrom:'(sleep 10; echo hello)'.
+     pipe canReadWithoutBlocking ifTrue:[
+	 Transcript showCr:'data available'
+     ] ifFalse:[
+	 Transcript showCr:'no data available'
+     ].
+     pipe close
+    "
+!
+
+canWriteWithoutBlocking
+    "return true, if data can be written into the stream 
+     (i.e. a write operation will not block the smalltalk process)."
+
+    |fd|
+
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    mode == #readonly ifTrue:[^ self errorReadOnly].
+
+    fd := self fileDescriptor.
+    ^ OperatingSystem writeCheck:fd
+! !
+
+!ExternalStream methodsFor:'waiting for I/O'!
+
+readWait
+    "suspend the current process, until the receiver
+     becomes ready for reading. If data is already available,
+     return immediate. 
+     The other threads are not affected by the wait."
+
+    self readWaitWithTimeoutMs:nil
+!
+
+readWaitWithTimeout:timeout
+    "suspend the current process, until the receiver
+     becomes ready for reading or a timeout (in seconds) expired. 
+     If data is already available, return immediate. 
+     Return true if a timeout occured (i.e. false, if data is available).
+     The other threads are not affected by the wait."
+
+    ^ self readWaitWithTimeoutMs:timeout * 1000
+!
+
+readWaitWithTimeoutMs:timeout 
+    "suspend the current process, until the receiver
+     becomes ready for reading or a timeout (in milliseconds) expired. 
+     If data is already available, return immediate. 
+     Return true if a timeout occured (i.e. false, if data is available).
+     The other threads are not affected by the wait."
+
+    |fd inputSema hasData wasBlocked|
+
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    mode == #writeonly ifTrue:[^ self errorWriteOnly].
+
+    fd := self fileDescriptor.
+    (OperatingSystem readCheck:fd) ifTrue:[^ false].
+
+    wasBlocked := OperatingSystem blockInterrupts.
+    hasData := OperatingSystem readCheck:fd.
+    hasData ifFalse:[
+	inputSema := Semaphore new.
+	[
+	    timeout notNil ifTrue:[
+		Processor signal:inputSema afterMilliseconds:timeout 
+	    ].
+	    Processor signal:inputSema onInput:fd.
+	    Processor activeProcess state:#ioWait.
+	    inputSema wait.
+	    Processor disableSemaphore:inputSema.
+	    hasData := OperatingSystem readCheck:fd
+	] valueOnUnwindDo:[
+	    Processor disableSemaphore:inputSema.
+	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+	]
+    ].
+    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+    ^ hasData not
+!
+
+writeWait
+    "suspend the current process, until the receiver
+     becomes ready for writing.
+     Return immediate if the receiver is already ready. 
+     The other threads are not affected by the wait."
+
+    self writeWaitWithTimeoutMs:nil
+!
+
+writeWaitWithTimeout:timeout
+    "suspend the current process, until the receiver
+     becomes ready for writing or a timeout (in seconds) expired. 
+     Return true if a timeout occured (i.e. false, if data is available).
+     Return immediate if the receiver is already ready. 
+     The other threads are not affected by the wait."
+
+    ^ self writeWaitWithTimeoutMs:timeout * 1000
+!
+
+writeWaitWithTimeoutMs:timeout
+    "suspend the current process, until the receiver
+     becomes ready for writing or a timeout (in seconds) expired. 
+     Return true if a timeout occured (i.e. false, if data is available).
+     Return immediate if the receiver is already ready. 
+     The other threads are not affected by the wait."
+
+    |fd outputSema canWrite wasBlocked|
+
+    filePointer isNil ifTrue:[
+	^ self errorNotOpen
+    ].
+    mode == #readonly ifTrue:[
+	^ self errorReadOnly
+    ].
+
+    fd := self fileDescriptor.
+    (OperatingSystem writeCheck:fd) ifTrue:[^ false].
+
+    wasBlocked := OperatingSystem blockInterrupts.
+    canWrite := OperatingSystem writeCheck:fd.
+    canWrite ifFalse:[
+	outputSema := Semaphore new.
+	[
+	    timeout notNil ifTrue:[
+		Processor signal:outputSema afterMilliseconds:timeout
+	    ].
+	    Processor signal:outputSema onOutput:fd.
+	    Processor activeProcess state:#ioWait.
+	    outputSema wait.
+	    Processor disableSemaphore:outputSema.
+	    canWrite := OperatingSystem writeCheck:fd
+	] valueOnUnwindDo:[
+	    Processor disableSemaphore:outputSema.
+	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+	]
+    ].
+    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+    ^ canWrite not
+! !
+
+!ExternalStream methodsFor:'writing'!
+
+commit
+    "write all buffered date - ignored if unbuffered"
+
+    self synchronizeOutput
+!
+
+cr
+    "append an end-of-line character (or CRLF if in crlf mode).
+     reimplemented for speed"
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    int len, cnt;
+    OBJ fp;
+    char *cp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))) {
+	if (_INST(binary) != true) {
+	    f = __FILEVal(fp);
+
+	    if (_INST(useCRLF) == true) {
+		cp = "\r\n"; len = 2;
+	    } else {
+		cp = "\n"; len = 1;
+	    }
+	    __BEGIN_INTERRUPTABLE__
+
+	    if (_INST(buffered) == true) {
+		__WRITING__(f)
+		cnt = fwrite(cp, 1, len, f);
+	    } else {
+		do {
+		    cnt = write(fileno(f), cp, len);
+		} while ((cnt < 0) && (errno == EINTR));
+	    }
+
+	    __END_INTERRUPTABLE__
+
+	    if (cnt == len) {
+		if (_INST(position) != nil) {
+		    _INST(position) = __MKSMALLINT(__intVal(_INST(position)) + len);
+		}
+		RETURN ( self );
+	    }
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+    self errorBinary
+!
+
+nextPut:aCharacter
+    "write the argument, aCharacter - return nil if failed, self if ok.
+     Only single-byte characters are currently supported"
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    char c;
+    int cnt;
+    OBJ pos, fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil) 
+     && (_INST(mode) != @symbol(readonly))) {
+	if (_INST(binary) != true) {
+	    if (__isCharacter(aCharacter)) {
+		c = __intVal(__characterVal(aCharacter)) & 0xFF;
+    doWrite:
+		f = __FILEVal(fp);
+
+		__BEGIN_INTERRUPTABLE__
+
+		if (_INST(buffered) == true) {
+		    __WRITING__(f)
+
+		    do {
+			cnt = fwrite(&c, 1, 1, f);
+		    } while ((cnt != 1) && (errno == EINTR));
+		} else {
+		    do {
+			cnt = write(fileno(f), &c, 1);
+		    } while ((cnt != 1) && (errno == EINTR));
+		}
+
+		__END_INTERRUPTABLE__
+
+		if (cnt == 1) {
+		    pos = _INST(position);
+		    if (pos != nil) {
+			_INST(position) = __MKSMALLINT(__intVal(pos) + 1);
+		    }
+		    RETURN ( self );
+		}
+		_INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    }
+	} else {
+	    if (__isSmallInteger(aCharacter)) {
+		c = __intVal(aCharacter);
+		goto doWrite;
+	    }
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+    binary ifFalse:[^ self argumentMustBeCharacter].
+    ^ self argumentMustBeInteger.
+!
+
+nextPutAll:aCollection
+    "write all elements of the argument, aCollection.
+     Reimplemented for speed when writing strings or byteArrays.
+     For others, falls back to general method in superclass."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    unsigned char *cp;
+    int len, cnt;
+    OBJ pos, fp;
+    int offs;
+
+    _INST(lastErrorNumber) = nil;
+
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))) {
+	cp = NULL;
+	offs = 0;
+	if (__isString(aCollection) || __isSymbol(aCollection)) {
+	    cp = _stringVal(aCollection);
+	    len = _stringSize(aCollection);
+	} else {
+	    if (_INST(binary) == true) {
+		if (__isByteArray(aCollection)) {
+		    cp = __ByteArrayInstPtr(aCollection)->ba_element;
+		    len = _byteArraySize(aCollection);
+		} else {
+		    if (__isBytes(aCollection)) {
+			int nInst;
+
+			cp = __ByteArrayInstPtr(aCollection)->ba_element;
+			len = _byteArraySize(aCollection);
+			nInst = __intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars);
+			offs = __OBJS2BYTES__(nInst);
+			cp += offs;
+			len -= offs;
+		    }
+		}
+	    }
+	}
+	if (cp != NULL) {
+	    f = __FILEVal(fp);
+
+	    __BEGIN_INTERRUPTABLE__
+
+	    if (_INST(buffered) == false) {
+		int cc, rest;
+
+		cnt = 0;
+		do {
+		    /*
+		     * refetch pointer in case of an interrupt
+		     */
+		    cp = __ByteArrayInstPtr(aCollection)->ba_element + offs;
+		    cnt = write(fileno(f), cp, len);
+		} while ((cnt < 0) && (errno == EINTR));
+	    } else {
+		__WRITING__(f)
+		cnt = fwrite(cp, 1, len, f);
+		if (errno == EINTR) errno = 0;
+	    }
+
+	    __END_INTERRUPTABLE__
+
+	    if (cnt == len) {
+		pos = _INST(position);
+		if (pos != nil) {
+		    _INST(position) = __MKSMALLINT(__intVal(pos) + len);
+		}
+		RETURN ( self );
+	    }
+	    _INST(lastErrorNumber) = __MKSMALLINT(errno);
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+    filePointer isNil ifTrue:[^ self errorNotOpen].
+    (mode == #readonly) ifTrue:[^ self errorReadOnly].
+
+    ^ super nextPutAll:aCollection
+!
+
+nextPutAll:aCollection startingAt:start to:stop
+    "write a range of elements of the argument, aCollection.
+     Reimplemented for speed when writing strings or byteArrays.
+     For others, falls back to general method in superclass."
+
+%{  /* NOCONTEXT */
+
+    FILE *f;
+    unsigned char *cp;
+    int offs, len, cnt, index1, index2;
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if (((fp = _INST(filePointer)) != nil)
+     && (_INST(mode) != @symbol(readonly))) {
+	if (__bothSmallInteger(start, stop)) {
+	    cp = NULL;
+	    offs = 0;
+	    if (_INST(binary) != true) {
+		if (__isString(aCollection) || __isSymbol(aCollection)) {
+		    cp = _stringVal(aCollection);
+		    len = _stringSize(aCollection);
+		}
+	    } else {
+		if (__isByteArray(aCollection)) {
+		    cp = __ByteArrayInstPtr(aCollection)->ba_element;
+		    len = _byteArraySize(aCollection);
+		} else {
+		    if (__isBytes(aCollection)) {
+			int nInst;
+
+			cp = __ByteArrayInstPtr(aCollection)->ba_element;
+			len = _byteArraySize(aCollection);
+			nInst = __intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars);
+			offs = __OBJS2BYTES__(nInst);
+			cp += offs;
+			len -= offs;
+		    }
+		}
+	    }
+
+	    if (cp != NULL) {
+		f = __FILEVal(fp);
+
+		index1 = __intVal(start);
+		index2 = __intVal(stop);
+		if ((index1 < 1) || (index2 > len) || (index2 < index1)) {
+		    RETURN ( self );
+		}
+		if (index2 > len)
+		    index2 = len;
+
+		len = index2 - index1 + 1;
+
+		__BEGIN_INTERRUPTABLE__
+
+		if (_INST(buffered) == true) {
+		    __WRITING__(f)
+		    cnt = fwrite(cp+index1-1, 1, len, f);
+		} else {
+		    do {
+			cp = __ByteArrayInstPtr(aCollection)->ba_element + offs;
+			cnt = write(fileno(f), cp+offs, len);
+		    } while ((cnt < 0) && (errno == EINTR));
+		}
+
+		__END_INTERRUPTABLE__
+
+		if (cnt == len) {
+		    if (_INST(position) != nil) {
+			_INST(position) = __MKSMALLINT(__intVal(_INST(position)) + len);
+		    }
+		    RETURN ( self );
+		}
+		_INST(lastErrorNumber) = __MKSMALLINT(errno);
+	    }
+	}
+    }
+%}.
+    lastErrorNumber notNil ifTrue:[^ self writeError].
+    ^ super nextPutAll:aCollection startingAt:start to:stop
+!
+
+synchronizeOutput
+    "write all buffered data - ignored if unbuffered"
+
+%{  /* NOCONTEXT */
+    OBJ fp;
+
+    _INST(lastErrorNumber) = nil;
+    if ((fp = _INST(filePointer)) != nil) {
+	if (_INST(mode) != @symbol(readonly)) {
+	    if (_INST(buffered) == true) {
+		__BEGIN_INTERRUPTABLE__
+		fflush( __FILEVal(fp) );
+		__END_INTERRUPTABLE__
+	    }
+	}
+    }
+%}
+! !
+
+ExternalStream initialize!