ExternalStream.st
branchjv
changeset 20728 83c74234945e
parent 20580 bb4e5c4f84ef
parent 20690 f6a11f77b230
child 21024 8734987eb5c7
equal deleted inserted replaced
20727:fb8c5591428b 20728:83c74234945e
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 1988 by Claus Gittinger
     4  COPYRIGHT (c) 1988 by Claus Gittinger
     3 	      All Rights Reserved
     5 	      All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
  2119 
  2121 
  2120 %{
  2122 %{
  2121     OBJ _handle  = __INST(handle);
  2123     OBJ _handle  = __INST(handle);
  2122 
  2124 
  2123     if (_handle != nil) {
  2125     if (_handle != nil) {
  2124 	if ((__INST(handleType) == @symbol(fileHandle))
  2126         if ((__INST(handleType) == @symbol(fileHandle))
  2125 	 || (__INST(handleType) == @symbol(socketHandle))) {
  2127          || (__INST(handleType) == @symbol(socketHandle))) {
  2126 	    RETURN (_handle);
  2128             RETURN (_handle);
  2127 	}
  2129         }
  2128 	if ((__INST(handleType) == nil)
  2130         if ((__INST(handleType) == nil)
  2129 	 || (__INST(handleType) == @symbol(filePointer))
  2131          || (__INST(handleType) == @symbol(filePointer))
  2130 	 || (__INST(handleType) == @symbol(socketFilePointer))
  2132          || (__INST(handleType) == @symbol(socketFilePointer))
  2131 	 || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2133          || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2132 #ifdef __win32__
  2134 #ifdef __win32__
  2133 	    RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle)))));
  2135             RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle)))));
  2134 #else
  2136 #else
  2135 	    RETURN (__MKINT(fileno(__FILEVal(_handle))));
  2137             RETURN (__MKINT(fileno(__FILEVal(_handle))));
  2136 #endif
  2138 #endif
  2137 	}
  2139         }
  2138     }
  2140     }
  2139 %}.
  2141 %}.
  2140     handle isNil ifTrue:[^ self errorNotOpen].
       
  2141     ^ handle
  2142     ^ handle
  2142 !
  2143 !
  2143 
  2144 
  2144 filePointer
  2145 filePointer
  2145     "return the filePointer of the receiver -
  2146     "return the filePointer of the receiver -
  2215     mode := #writeonly
  2216     mode := #writeonly
  2216 ! !
  2217 ! !
  2217 
  2218 
  2218 !ExternalStream methodsFor:'closing'!
  2219 !ExternalStream methodsFor:'closing'!
  2219 
  2220 
       
  2221 abortAndClose
       
  2222     "close the stream - added for protocol compatibility with Socket and PipeStream.
       
  2223      see comment there"
       
  2224 
       
  2225     self close.
       
  2226 
       
  2227     "Modified: 30.8.1996 / 00:39:21 / cg"
       
  2228 !
       
  2229 
  2220 close
  2230 close
  2221     "Close the stream.
  2231     "Close the stream.
  2222      No error if the stream is not open."
  2232      No error if the stream is not open."
  2223 
  2233 
  2224     self isOpen ifTrue:[
  2234     self isOpen ifTrue:[
  2228         ].
  2238         ].
  2229     ].
  2239     ].
  2230 !
  2240 !
  2231 
  2241 
  2232 shutDown
  2242 shutDown
  2233     "close the stream - added for protocol compatibility with PipeStream.
  2243     "close the stream - added for protocol compatibility with Socket.
  2234      see comment there"
  2244      see comment there"
  2235 
  2245 
  2236     self close.
  2246     self close.
  2237 
  2247 
  2238     "Modified: 30.8.1996 / 00:39:21 / cg"
  2248     "Modified: 30.8.1996 / 00:39:21 / cg"
  2519 !
  2529 !
  2520 
  2530 
  2521 finalize
  2531 finalize
  2522     "some Stream has been collected - close the file if not already done"
  2532     "some Stream has been collected - close the file if not already done"
  2523 
  2533 
  2524     "/ with timeout to avoid blocking in a bad pty/socket
  2534     self closeFile
  2525     [
       
  2526 	self closeFile
       
  2527     ] valueWithTimeout:30 seconds.
       
  2528 !
  2535 !
  2529 
  2536 
  2530 reRegisterForFinalization
  2537 reRegisterForFinalization
  2531     Lobby registerChange:self.
  2538     Lobby registerChange:self.
  2532 !
  2539 !
  4625     self nextPutUtf16Bytes:aCharacter MSB:true
  4632     self nextPutUtf16Bytes:aCharacter MSB:true
  4626 
  4633 
  4627     "
  4634     "
  4628         (FileStream newTemporary
  4635         (FileStream newTemporary
  4629             nextPutUtf16:$B;
  4636             nextPutUtf16:$B;
  4630             nextPutUtf16:$Ä;
  4637             nextPutUtf16:$Ä;
  4631             nextPutUtf16:(Character codePoint:16r10CCCC);
  4638             nextPutUtf16:(Character codePoint:16r10CCCC);
  4632             reset;
  4639             reset;
  4633             binary;
  4640             binary;
  4634             contents)
  4641             contents)
  4635     "
  4642     "
  4664 
  4671 
  4665 !ExternalStream methodsFor:'private'!
  4672 !ExternalStream methodsFor:'private'!
  4666 
  4673 
  4667 clearEOF
  4674 clearEOF
  4668     hitEOF := false
  4675     hitEOF := false
  4669 !
  4676 ! !
       
  4677 
       
  4678 !ExternalStream protectedMethodsFor:'private'!
  4670 
  4679 
  4671 closeFile
  4680 closeFile
  4672     "low level close - may be redefined in subclasses
  4681     "low level close - may be redefined in subclasses
  4673      Don't send this message, send #close instead"
  4682      Don't send this message, send #close instead"
  4674 
  4683 
  4675     |fp error|
  4684     |fp error|
  4676 
  4685 
       
  4686     handle isNil ifTrue:[
       
  4687         ^ self.
       
  4688     ].
  4677     fp := handle.
  4689     fp := handle.
  4678     "/ (didWrite==true and:[binary ~~ true and:[eolMode = #crlf]]) ifTrue: [ self breakPoint:#sr ].
  4690     "/ (didWrite==true and:[binary ~~ true and:[eolMode = #crlf]]) ifTrue: [ self breakPoint:#sr ].
  4679 
  4691 
  4680 %{
  4692 %{
  4681     int rslt;
  4693     int rslt;
  4682 
  4694 
  4683     if (fp == nil) {
       
  4684 	error = @symbol(errorNotOpen);
       
  4685 	goto out;
       
  4686     }
       
  4687 
       
  4688     if (__INST(handleType) == @symbol(socketHandle)) {
  4695     if (__INST(handleType) == @symbol(socketHandle)) {
  4689 	SOCKET sock = (SOCKET)(__FILEVal(fp));
  4696         SOCKET sock = (SOCKET)(__FILEVal(fp));
  4690 
  4697 
  4691 	if (@global(FileOpenTrace) == true) {
  4698         if (@global(FileOpenTrace) == true) {
  4692 	    fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", (INT)sock);
  4699             fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", (INT)sock);
  4693 	}
  4700         }
  4694 
  4701 
  4695 	// whether the close() will be successful or not - the handle is invalid now!
  4702         // whether the close() will be successful or not - the handle is invalid now!
  4696 	__INST(handle) = nil;
  4703         __INST(handle) = nil;
  4697 	do {
  4704         do {
  4698 #ifdef __win32__
  4705 #ifdef __win32__
  4699 	    rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock);
  4706             rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock);
  4700 #else
  4707 #else
  4701 	    rslt = close(sock);
  4708             rslt = close(sock);
  4702 #endif
  4709 #endif
  4703 	} while((rslt < 0) && (__threadErrno == EINTR));
  4710         } while((rslt < 0) && (__threadErrno == EINTR));
  4704     } else if ((__INST(handleType) == nil)
  4711     } else if ((__INST(handleType) == nil)
  4705 	       || (__INST(handleType) == @symbol(filePointer))
  4712                || (__INST(handleType) == @symbol(filePointer))
  4706 	       || (__INST(handleType) == @symbol(socketFilePointer))
  4713                || (__INST(handleType) == @symbol(socketFilePointer))
  4707 	       || (__INST(handleType) == @symbol(pipeFilePointer)))
  4714                || (__INST(handleType) == @symbol(pipeFilePointer)))
  4708     {
  4715     {
  4709 	FILEPOINTER f = __FILEVal(fp);
  4716         FILEPOINTER f = __FILEVal(fp);
  4710 
  4717 
  4711 	if (@global(FileOpenTrace) == true) {
  4718         if (@global(FileOpenTrace) == true) {
  4712 	    fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f);
  4719             fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f);
  4713 	}
  4720         }
  4714 	// whether the close() will be successful or not - the handle is invalid now!
  4721         // whether the close() will be successful or not - the handle is invalid now!
  4715 	__INST(handle) = nil;
  4722         __INST(handle) = nil;
  4716 
  4723 
  4717 #ifdef __win32__
  4724 #ifdef __win32__
  4718 	if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) {
  4725         if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) {
  4719 	    // do a fflush() first, so that fclose() doesn't block
  4726             // do a fflush() first, so that fclose() doesn't block
  4720 	    // we suspect, that EINTR causes problems in fclose()
  4727             // we suspect, that EINTR causes problems in fclose()
  4721 	    do {
  4728             do {
  4722 		__threadErrno = 0;
  4729                 __threadErrno = 0;
  4723 		rslt = __STX_C_CALL1("fflush", fflush, f);
  4730                 rslt = __STX_C_CALL1("fflush", fflush, f);
  4724 	    } while((rslt < 0) && (__threadErrno == EINTR));
  4731             } while((rslt < 0) && (__threadErrno == EINTR));
  4725 	}
  4732         }
  4726 	do {
  4733         do {
  4727 	    __threadErrno = 0;
  4734             __threadErrno = 0;
  4728 	    rslt = __STX_C_NOINT_CALL1("fclose", fclose, f);
  4735             rslt = __STX_C_NOINT_CALL1("fclose", fclose, f);
  4729 	} while((rslt < 0) && (__threadErrno == EINTR));
  4736         } while((rslt < 0) && (__threadErrno == EINTR));
  4730 #else
  4737 #else
  4731 	// cg: the pre Nov2014 code always did the fclose interruptable;
  4738         // cg: the pre Nov2014 code always did the fclose interruptable;
  4732 	// I am not sure, if fclose is actually prepared to do this;
  4739         // I am not sure, if fclose is actually prepared to do this;
  4733 	// at least when only reading, this should not block, and we
  4740         // at least when only reading, this should not block, and we
  4734 	// should be ableto do it without being interruptable.
  4741         // should be ableto do it without being interruptable.
  4735 	// Must watch this - if it leads to blockings, change and think about it.
  4742         // Must watch this - if it leads to blockings, change and think about it.
  4736 	if (__INST(mode) != @symbol(readonly)) {
  4743         if (__INST(mode) != @symbol(readonly)) {
  4737 	    __BEGIN_INTERRUPTABLE__
  4744             __BEGIN_INTERRUPTABLE__
  4738 	    rslt = fclose(f);
  4745             rslt = fclose(f);
  4739 	    __END_INTERRUPTABLE__
  4746             __END_INTERRUPTABLE__
  4740 	} else {
  4747         } else {
  4741 	    rslt = fclose(f);
  4748             rslt = fclose(f);
  4742 	}
  4749         }
  4743 #endif
  4750 #endif
  4744     } else {
  4751     } else {
  4745 	error = @symbol(badHandleType);
  4752         error = @symbol(badHandleType);
  4746 	goto out;
  4753         goto out;
  4747     }
  4754     }
  4748 
  4755 
  4749     if (rslt < 0) {
  4756     if (rslt < 0) {
  4750 	error = __mkSmallInteger(__threadErrno);
  4757         error = __mkSmallInteger(__threadErrno);
  4751 	goto out;
  4758         goto out;
  4752     }
  4759     }
  4753     RETURN (self);
  4760     RETURN (self);
  4754 
  4761 
  4755 out:;
  4762 out:;
  4756 %}.
  4763 %}.
  4757 
  4764 
  4758     error notNil ifTrue:[
  4765     error notNil ifTrue:[
  4759 	error == #errorNotOpen ifTrue:[
  4766         error isInteger ifTrue:[
  4760 	    self errorNotOpen.
  4767             lastErrorNumber := error.
  4761 	].
  4768             mode == #readonly ifTrue:[
  4762 	error isInteger ifTrue:[
  4769                 self ioError:error.
  4763 	    lastErrorNumber := error.
  4770             ] ifFalse:[
  4764 	    mode == #readonly ifTrue:[
  4771                 self writeError:error.
  4765 		self ioError:error.
  4772             ].
  4766 	    ] ifFalse:[
  4773             ^ self.
  4767 		self writeError:error.
  4774         ].
  4768 	    ].
  4775         self primitiveFailed:error.
  4769 	    ^ self.
  4776         ^ self.
  4770 	].
       
  4771 	self primitiveFailed:error.
       
  4772 	^ self.
       
  4773     ].
  4777     ].
  4774 
  4778 
  4775     "/ fallback for rel5
  4779     "/ fallback for rel5
  4776 
  4780 
  4777     fp := handle.
  4781     fp := handle.
  4778     fp notNil ifTrue:[
  4782     fp notNil ifTrue:[
  4779 	handle := nil.
  4783         handle := nil.
  4780 	self closeFile:fp
  4784         self closeFile:fp
  4781     ]
  4785     ]
  4782 !
  4786 ! !
       
  4787 
       
  4788 !ExternalStream methodsFor:'private'!
  4783 
  4789 
  4784 closeFile:handle
  4790 closeFile:handle
  4785     "for rel5 only"
  4791     "for rel5 only"
  4786 
  4792 
  4787     self primitiveFailed
  4793     self primitiveFailed
  4868     "duplicate my file descriptor"
  4874     "duplicate my file descriptor"
  4869 
  4875 
  4870     |fd dupFd|
  4876     |fd dupFd|
  4871 
  4877 
  4872     fd := self fileHandle.
  4878     fd := self fileHandle.
       
  4879     fd isNil ifTrue:[   
       
  4880         ^ self errorNotOpen.
       
  4881     ].
  4873     dupFd := OperatingSystem dup:fd.
  4882     dupFd := OperatingSystem dup:fd.
  4874     self setFileHandle:dupFd mode:self fopenMode.
  4883     self setFileHandle:dupFd mode:self fopenMode.
  4875 !
  4884 !
  4876 
  4885 
  4877 fopenMode
  4886 fopenMode
  5148 %{
  5157 %{
  5149 #ifdef __SCHTEAM__
  5158 #ifdef __SCHTEAM__
  5150     STObject handle = self.instVarAt(I_handle);
  5159     STObject handle = self.instVarAt(I_handle);
  5151 
  5160 
  5152     if (handle != STObject.Nil) {
  5161     if (handle != STObject.Nil) {
  5153 	STObject next;
  5162         STObject next;
  5154 
  5163 
  5155 	if (self.instVarAt(I_binary) == STObject.True) {
  5164         if (self.instVarAt(I_binary) == STObject.True) {
  5156 	    next = handle.nextByte();
  5165             next = handle.nextByte();
  5157 	} else {
  5166         } else {
  5158 	    next = handle.nextChar();
  5167             next = handle.nextChar();
  5159 	}
  5168         }
  5160 	if (next != STObject.EOF) {
  5169         if (next != STObject.EOF) {
  5161 	    self.instVarAt_put(I_position, STObject.Nil);
  5170             self.instVarAt_put(I_position, STObject.Nil);
  5162 	    return __c__._RETURN( next );
  5171             return __c__._RETURN( next );
  5163 	}
  5172         }
  5164 	self.instVarAt_put(I_hitEOF, STObject.True);
  5173         self.instVarAt_put(I_hitEOF, STObject.True);
  5165     }
  5174     }
  5166 #else
  5175 #else
  5167     FILEPOINTER f;
  5176     FILEPOINTER f;
  5168     int ret, _buffered;
  5177     int ret, _buffered;
  5169     OBJ pos, fp;
  5178     OBJ pos, fp;
  5173     if ((__INST(handleType) == nil)
  5182     if ((__INST(handleType) == nil)
  5174      || (__INST(handleType) == @symbol(filePointer))
  5183      || (__INST(handleType) == @symbol(filePointer))
  5175      || (__INST(handleType) == @symbol(socketFilePointer))
  5184      || (__INST(handleType) == @symbol(socketFilePointer))
  5176      || (__INST(handleType) == @symbol(socketHandle))
  5185      || (__INST(handleType) == @symbol(socketHandle))
  5177      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5186      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5178 	if (((fp = __INST(handle)) != nil)
  5187         if (((fp = __INST(handle)) != nil)
  5179 	    && (__INST(mode) != @symbol(writeonly))
  5188             && (__INST(mode) != @symbol(writeonly))
  5180 	) {
  5189         ) {
  5181 	    f = __FILEVal(fp);
  5190             f = __FILEVal(fp);
  5182 
  5191 
  5183 	    _buffered = (__INST(buffered) == true);
  5192             _buffered = (__INST(buffered) == true);
  5184 	    if (_buffered) {
  5193             if (_buffered) {
  5185 		__READING__(f)
  5194                 __READING__(f)
  5186 	    }
  5195             }
  5187 	    __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  5196             __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  5188 
  5197 
  5189 	    if (ret > 0) {
  5198             if (ret > 0) {
  5190 		pos = __INST(position);
  5199                 pos = __INST(position);
  5191 		if (__isSmallInteger(pos)) {
  5200                 if (__isSmallInteger(pos)) {
  5192 		    OBJ t;
  5201                     OBJ t;
  5193 
  5202 
  5194 		    t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  5203                     t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  5195 		} else {
  5204                 } else {
  5196 		    __INST(position) = nil; /* i.e. do not know */
  5205                     __INST(position) = nil; /* i.e. do not know */
  5197 		}
  5206                 }
  5198 		if (__INST(binary) == true) {
  5207                 if (__INST(binary) == true) {
  5199 		    RETURN ( __mkSmallInteger(ch) );
  5208                     RETURN ( __mkSmallInteger(ch) );
  5200 		}
  5209                 }
  5201 		RETURN ( __MKCHARACTER(ch) );
  5210                 RETURN ( __MKCHARACTER(ch) );
  5202 	    }
  5211             }
  5203 
  5212 
  5204 	    __INST(position) = nil;
  5213             __INST(position) = nil;
  5205 	    if ((ret < 0)
  5214             if (ret < 0) {
  5206 # ifdef ECONNRESET
  5215                 error = __mkSmallInteger(__threadErrno);
  5207 		&& (__threadErrno != ECONNRESET)
  5216             } else /* ret == 0 */ {
  5208 # endif
  5217                 __INST(hitEOF) = true;
  5209 	    ){
  5218             }
  5210 		error = __mkSmallInteger(__threadErrno);
  5219         }
  5211 	    } else /* ret == 0 */ {
       
  5212 		__INST(hitEOF) = true;
       
  5213 	    }
       
  5214 	}
       
  5215     }
  5220     }
  5216 #endif /* not SCHTEAM */
  5221 #endif /* not SCHTEAM */
  5217 %}.
  5222 %}.
  5218     hitEOF == true ifTrue:[^ self pastEndRead].
  5223     hitEOF == true ifTrue:[^ self pastEndRead].
  5219     error notNil ifTrue:[
  5224     error notNil ifTrue:[
  5220 	lastErrorNumber := error.
  5225         lastErrorNumber := error.
  5221 	^ self readError:error
  5226         ^ self readError:error
  5222     ].
  5227     ].
  5223     handle isNil ifTrue:[^ self errorNotOpen].
  5228     handle isNil ifTrue:[^ self errorNotOpen].
  5224     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5229     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5225 
  5230 
  5226     readAhead notNil ifTrue:[
  5231     readAhead notNil ifTrue:[
  5227 	c := readAhead.
  5232         c := readAhead.
  5228 	readAhead := nil.
  5233         readAhead := nil.
  5229 	^ c.
  5234         ^ c.
  5230     ].
  5235     ].
       
  5236 
       
  5237     "unknown handleType - future"
  5231     c := self nextByteFromFile:handle.
  5238     c := self nextByteFromFile:handle.
  5232     c isNil ifTrue:[
  5239     c isNil ifTrue:[
  5233 	^ self pastEndRead.
  5240         ^ self pastEndRead.
  5234     ].
  5241     ].
  5235     binary == true ifTrue:[
  5242     binary == true ifTrue:[
  5236 	^ c
  5243         ^ c
  5237     ].
  5244     ].
  5238     ^ Character value:c
  5245     ^ Character value:c
  5239 !
  5246 !
  5240 
  5247 
  5241 next:count
  5248 next:count
  5274     if ((__INST(handleType) == nil)
  5281     if ((__INST(handleType) == nil)
  5275      || (__INST(handleType) == @symbol(filePointer))
  5282      || (__INST(handleType) == @symbol(filePointer))
  5276      || (__INST(handleType) == @symbol(socketFilePointer))
  5283      || (__INST(handleType) == @symbol(socketFilePointer))
  5277      || (__INST(handleType) == @symbol(socketHandle))
  5284      || (__INST(handleType) == @symbol(socketHandle))
  5278      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5285      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5279 	if (((fp = __INST(handle)) != nil)
  5286         if (((fp = __INST(handle)) != nil)
  5280 	    && (__INST(mode) != @symbol(writeonly))
  5287             && (__INST(mode) != @symbol(writeonly))
  5281 	) {
  5288         ) {
  5282 	    f = __FILEVal(fp);
  5289             f = __FILEVal(fp);
  5283 
  5290 
  5284 	    _buffered = (__INST(buffered) == true);
  5291             _buffered = (__INST(buffered) == true);
  5285 	    if (_buffered) {
  5292             if (_buffered) {
  5286 		__READING__(f)
  5293                 __READING__(f)
  5287 	    }
  5294             }
  5288 	    __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  5295             __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  5289 
  5296 
  5290 	    if (ret > 0) {
  5297             if (ret > 0) {
  5291 		pos = __INST(position);
  5298                 pos = __INST(position);
  5292 		if (__isSmallInteger(pos)) {
  5299                 if (__isSmallInteger(pos)) {
  5293 		    OBJ t;
  5300                     OBJ t;
  5294 
  5301 
  5295 		    t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  5302                     t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  5296 		} else {
  5303                 } else {
  5297 		    __INST(position) = nil; /* i.e. do not know */
  5304                     __INST(position) = nil; /* i.e. do not know */
  5298 		}
  5305                 }
  5299 		if (__INST(binary) == true) {
  5306                 if (__INST(binary) == true) {
  5300 		    RETURN ( __mkSmallInteger(ch) );
  5307                     RETURN ( __mkSmallInteger(ch) );
  5301 		}
  5308                 }
  5302 		RETURN ( __MKCHARACTER(ch) );
  5309                 RETURN ( __MKCHARACTER(ch) );
  5303 	    }
  5310             }
  5304 
  5311 
  5305 	    __INST(position) = nil;
  5312             __INST(position) = nil;
  5306 	    if ((ret < 0)
  5313             if (ret < 0) {
  5307 #ifdef ECONNRESET
  5314                 error = __mkSmallInteger(__threadErrno);
  5308 		&& (__threadErrno != ECONNRESET)
  5315             } else /* ret == 0 */ {
  5309 #endif
  5316                 __INST(hitEOF) = true;
  5310 	    ){
  5317             }
  5311 		error = __mkSmallInteger(__threadErrno);
  5318         }
  5312 	    } else /* ret == 0 */ {
       
  5313 		__INST(hitEOF) = true;
       
  5314 	    }
       
  5315 	}
       
  5316     }
  5319     }
  5317 %}.
  5320 %}.
  5318     hitEOF == true ifTrue:[^ nil].
  5321     hitEOF == true ifTrue:[^ nil].
  5319     error notNil ifTrue:[
  5322     error notNil ifTrue:[
  5320 	lastErrorNumber := error.
  5323         lastErrorNumber := error.
  5321 	^ self readError:error.
  5324         ^ self readError:error.
  5322     ].
  5325     ].
  5323     handle isNil ifTrue:[^ self errorNotOpen].
  5326     handle isNil ifTrue:[^ self errorNotOpen].
  5324     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5327     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5325 
  5328 
  5326     readAhead notNil ifTrue:[
  5329     readAhead notNil ifTrue:[
  5327 	c := readAhead.
  5330         c := readAhead.
  5328 	readAhead := nil.
  5331         readAhead := nil.
  5329 	^ c.
  5332         ^ c.
  5330     ].
  5333     ].
       
  5334 
       
  5335     "unknown handleType - future"
  5331     c := self nextByteFromFile:handle.
  5336     c := self nextByteFromFile:handle.
  5332     c isNil ifTrue:[
  5337     c isNil ifTrue:[
  5333 	^ nil.
  5338         ^ nil.
  5334     ].
  5339     ].
  5335     binary == true ifTrue:[
  5340     binary == true ifTrue:[
  5336 	^ c
  5341         ^ c
  5337     ].
  5342     ].
  5338     ^ Character value:c
  5343     ^ Character value:c
  5339 !
  5344 !
  5340 
  5345 
  5341 peek
  5346 peek
  5351     int ret, _buffered;
  5356     int ret, _buffered;
  5352     OBJ fp;
  5357     OBJ fp;
  5353     OBJ ra;
  5358     OBJ ra;
  5354 
  5359 
  5355     if ((ra = __INST(readAhead)) != nil) {
  5360     if ((ra = __INST(readAhead)) != nil) {
  5356 	if (__INST(binary) == true) {
  5361         if (__INST(binary) == true) {
  5357 	    RETURN ( ra );
  5362             RETURN ( ra );
  5358 	}
  5363         }
  5359 	c = __intVal(ra);
  5364         c = __intVal(ra);
  5360 	RETURN ( __MKCHARACTER(c) );
  5365         RETURN ( __MKCHARACTER(c) );
  5361     }
  5366     }
  5362 
  5367 
  5363     __INST(lastErrorNumber) = nil;
  5368     __INST(lastErrorNumber) = nil;
  5364 
  5369 
  5365     if ((__INST(handleType) == nil)
  5370     if ((__INST(handleType) == nil)
  5366      || (__INST(handleType) == @symbol(filePointer))
  5371      || (__INST(handleType) == @symbol(filePointer))
  5367      || (__INST(handleType) == @symbol(socketFilePointer))
  5372      || (__INST(handleType) == @symbol(socketFilePointer))
  5368      || (__INST(handleType) == @symbol(socketHandle))
  5373      || (__INST(handleType) == @symbol(socketHandle))
  5369      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5374      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5370 	if (((fp = __INST(handle)) != nil)
  5375         if (((fp = __INST(handle)) != nil)
  5371 	    && (__INST(mode) != @symbol(writeonly))
  5376             && (__INST(mode) != @symbol(writeonly))
  5372 	) {
  5377         ) {
  5373 	    f = __FILEVal(fp);
  5378             f = __FILEVal(fp);
  5374 	    _buffered = (__INST(buffered) == true);
  5379             _buffered = (__INST(buffered) == true);
  5375 	    if (_buffered) {
  5380             if (_buffered) {
  5376 		__READING__(f)
  5381                 __READING__(f)
  5377 	    }
  5382             }
  5378 	    __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5383             __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5379 
  5384 
  5380 	    if (ret > 0) {
  5385             if (ret > 0) {
  5381 		__UNGETC__(c, f, _buffered);
  5386                 __UNGETC__(c, f, _buffered);
  5382 
  5387 
  5383 		if (__INST(binary) == true) {
  5388                 if (__INST(binary) == true) {
  5384 		    RETURN ( __mkSmallInteger(c) );
  5389                     RETURN ( __mkSmallInteger(c) );
  5385 		}
  5390                 }
  5386 		RETURN ( __MKCHARACTER(c) );
  5391                 RETURN ( __MKCHARACTER(c) );
  5387 	    }
  5392             }
  5388 	    if ((ret < 0)
  5393             if (ret < 0) {
  5389 #ifdef ECONNRESET
  5394                 error = __mkSmallInteger(__threadErrno);
  5390 		&& (__threadErrno != ECONNRESET)
  5395             } else /* ret == 0 */ {
  5391 #endif
  5396                 __INST(hitEOF) = true;
  5392 	    ){
  5397             }
  5393 		error = __mkSmallInteger(__threadErrno);
  5398         }
  5394 	    } else /* ret == 0 */ {
       
  5395 		__INST(hitEOF) = true;
       
  5396 	    }
       
  5397 	}
       
  5398     }
  5399     }
  5399 %}.
  5400 %}.
  5400     hitEOF == true ifTrue:[^ self pastEndRead].
  5401     hitEOF == true ifTrue:[^ self pastEndRead].
  5401     error notNil ifTrue:[
  5402     error notNil ifTrue:[
  5402 	lastErrorNumber := error.
  5403         lastErrorNumber := error.
  5403 	^ self readError:error.
  5404         ^ self readError:error.
  5404     ].
  5405     ].
  5405     handle isNil ifTrue:[^ self errorNotOpen].
  5406     handle isNil ifTrue:[^ self errorNotOpen].
  5406     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5407     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5407 
  5408 
  5408     readAhead isNil ifTrue:[
  5409     readAhead isNil ifTrue:[
  5409 	readAhead := self nextOrNil.
  5410         readAhead := self nextOrNil.
  5410 	readAhead isNil ifTrue:[
  5411         readAhead isNil ifTrue:[
  5411 	    ^ self pastEndRead.
  5412             ^ self pastEndRead.
  5412 	].
  5413         ].
  5413     ].
  5414     ].
  5414     ^ readAhead
  5415     ^ readAhead
  5415 !
  5416 !
  5416 
  5417 
  5417 peekOrNil
  5418 peekOrNil
  5427     int ret, _buffered;
  5428     int ret, _buffered;
  5428     OBJ fp;
  5429     OBJ fp;
  5429     OBJ ra;
  5430     OBJ ra;
  5430 
  5431 
  5431     if ((ra = __INST(readAhead)) != nil) {
  5432     if ((ra = __INST(readAhead)) != nil) {
  5432 	if (__INST(binary) == true) {
  5433         if (__INST(binary) == true) {
  5433 	    RETURN ( ra );
  5434             RETURN ( ra );
  5434 	}
  5435         }
  5435 	c = __intVal(ra);
  5436         c = __intVal(ra);
  5436 	RETURN ( __MKCHARACTER(c) );
  5437         RETURN ( __MKCHARACTER(c) );
  5437     }
  5438     }
  5438 
  5439 
  5439     __INST(lastErrorNumber) = nil;
  5440     __INST(lastErrorNumber) = nil;
  5440 
  5441 
  5441     if ((__INST(handleType) == nil)
  5442     if ((__INST(handleType) == nil)
  5442      || (__INST(handleType) == @symbol(filePointer))
  5443      || (__INST(handleType) == @symbol(filePointer))
  5443      || (__INST(handleType) == @symbol(socketFilePointer))
  5444      || (__INST(handleType) == @symbol(socketFilePointer))
  5444      || (__INST(handleType) == @symbol(socketHandle))
  5445      || (__INST(handleType) == @symbol(socketHandle))
  5445      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5446      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5446 	if (((fp = __INST(handle)) != nil)
  5447         if (((fp = __INST(handle)) != nil)
  5447 	    && (__INST(mode) != @symbol(writeonly))
  5448             && (__INST(mode) != @symbol(writeonly))
  5448 	) {
  5449         ) {
  5449 	    f = __FILEVal(fp);
  5450             f = __FILEVal(fp);
  5450 	    _buffered = (__INST(buffered) == true);
  5451             _buffered = (__INST(buffered) == true);
  5451 	    if (_buffered) {
  5452             if (_buffered) {
  5452 		__READING__(f)
  5453                 __READING__(f)
  5453 	    }
  5454             }
  5454 	    __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5455             __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5455 
  5456 
  5456 	    if (ret > 0) {
  5457             if (ret > 0) {
  5457 		__UNGETC__(c, f, _buffered);
  5458                 __UNGETC__(c, f, _buffered);
  5458 
  5459 
  5459 		if (__INST(binary) == true) {
  5460                 if (__INST(binary) == true) {
  5460 		    RETURN ( __mkSmallInteger(c) );
  5461                     RETURN ( __mkSmallInteger(c) );
  5461 		}
  5462                 }
  5462 		RETURN ( __MKCHARACTER(c) );
  5463                 RETURN ( __MKCHARACTER(c) );
  5463 	    }
  5464             }
  5464 	    if ((ret < 0)
  5465             if (ret < 0) {
  5465 #ifdef ECONNRESET
  5466                 error = __mkSmallInteger(__threadErrno);
  5466 		&& (__threadErrno != ECONNRESET)
  5467             } else /* ret == 0 */ {
  5467 #endif
  5468                 __INST(hitEOF) = true;
  5468 	    ){
  5469             }
  5469 		error = __mkSmallInteger(__threadErrno);
  5470         }
  5470 	    } else /* ret == 0 */ {
       
  5471 		__INST(hitEOF) = true;
       
  5472 	    }
       
  5473 	}
       
  5474     }
  5471     }
  5475 %}.
  5472 %}.
  5476     hitEOF == true ifTrue:[^ nil].
  5473     hitEOF == true ifTrue:[^ nil].
  5477     error notNil ifTrue:[
  5474     error notNil ifTrue:[
  5478 	lastErrorNumber := error.
  5475         lastErrorNumber := error.
  5479 	^ self readError:error.
  5476         ^ self readError:error.
  5480     ].
  5477     ].
  5481     handle isNil ifTrue:[^ self errorNotOpen].
  5478     handle isNil ifTrue:[^ self errorNotOpen].
  5482     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5479     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5483 
  5480 
  5484     readAhead isNil ifTrue:[
  5481     readAhead isNil ifTrue:[
  5485 	readAhead := self nextOrNil.
  5482         readAhead := self nextOrNil.
  5486     ].
  5483     ].
  5487     ^ readAhead
  5484     ^ readAhead
  5488 !
  5485 !
  5489 
  5486 
  5490 upToEnd
  5487 upToEnd
  5563 ! !
  5560 ! !
  5564 
  5561 
  5565 !ExternalStream methodsFor:'testing'!
  5562 !ExternalStream methodsFor:'testing'!
  5566 
  5563 
  5567 atEnd
  5564 atEnd
  5568     "return true, if position is at end"
  5565     "return true, if position is at end.
       
  5566      A stream is at the end, if the next read operation
       
  5567      would return immediately without waiting."
  5569 
  5568 
  5570 %{
  5569 %{
  5571     OBJ fp, pos, lim;
  5570     OBJ fp, pos, lim;
  5572     char c;
  5571     char c;
  5573 
  5572 
  5633             }
  5632             }
  5634             if (ret == 0) {
  5633             if (ret == 0) {
  5635                 __INST(hitEOF) = true;
  5634                 __INST(hitEOF) = true;
  5636                 RETURN (true);
  5635                 RETURN (true);
  5637             }
  5636             }
  5638 #ifdef ECONNRESET
  5637             /* ret < 0 -> error */
  5639             // connection reset by peer is also an EOF
       
  5640             if (__threadErrno == ECONNRESET) {
       
  5641                 __INST(hitEOF) = true;
       
  5642                 RETURN (true);
       
  5643             }
       
  5644 #endif
       
  5645             /* ret < 0 */
       
  5646             __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5638             __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5647         }
  5639         }
       
  5640         // we do not raise an error here - the next read operation will raise the error.
       
  5641         RETURN(false);
  5648     }
  5642     }
  5649 %}.
  5643 %}.
  5650     lastErrorNumber notNil ifTrue:[^ self readError].
  5644 
  5651     handle isNil ifTrue:[^ self errorNotOpen].
  5645     "/ we come here if the handle type is unknown 
  5652     mode == #writeonly ifTrue:[^ self errorWriteOnly].
       
  5653     readAhead notNil ifTrue:[^ false].
       
  5654 
       
  5655     "/ migration support
  5646     "/ migration support
  5656     ^ self
  5647     ^ self atEndFile:handle
  5657         atEndFile:handle
       
  5658 
  5648 
  5659     "Modified: / 30.10.1998 / 20:16:06 / cg"
  5649     "Modified: / 30.10.1998 / 20:16:06 / cg"
  5660 !
  5650 !
  5661 
  5651 
  5662 canReadWithoutBlocking
  5652 canReadWithoutBlocking
  5693 	or:[mode == #readonly
  5683 	or:[mode == #readonly
  5694 	or:[OperatingSystem writeCheck:self fileDescriptor]]
  5684 	or:[OperatingSystem writeCheck:self fileDescriptor]]
  5695 !
  5685 !
  5696 
  5686 
  5697 gotErrorOrEOF
  5687 gotErrorOrEOF
  5698     "answerv true, if amn error or eof has been occurred on the stream"
  5688     "answer true, if amn error or eof has been occurred on the stream"
  5699 
  5689 
  5700     ^ hitEOF == true or:[lastErrorNumber notNil]
  5690     ^ hitEOF == true or:[lastErrorNumber notNil]
  5701 !
  5691 !
  5702 
  5692 
  5703 isBinary
  5693 isBinary
  6577     aString do:[:eachCharacter|
  6567     aString do:[:eachCharacter|
  6578 	self nextPutUtf8:eachCharacter.
  6568 	self nextPutUtf8:eachCharacter.
  6579     ].
  6569     ].
  6580 
  6570 
  6581     "
  6571     "
  6582 	'Bönnigheim' asUnicode16String errorPrintCR
  6572 	'Bönnigheim' asUnicode16String errorPrintCR
  6583     "
  6573     "
  6584 !
  6574 !
  6585 
  6575 
  6586 nextPutBytes:count from:anObject startingAt:start
  6576 nextPutBytes:count from:anObject startingAt:start
  6587     "write count bytes from an object starting at index start.
  6577     "write count bytes from an object starting at index start.