FileStream.st
changeset 8627 5a86b95bebbb
parent 8604 3079fcbdecb2
child 8768 0036c76202c5
equal deleted inserted replaced
8626:ae1fcb227a45 8627:5a86b95bebbb
    31 #ifdef transputer
    31 #ifdef transputer
    32 # include <iocntrl.h>
    32 # include <iocntrl.h>
    33 # ifndef fileno
    33 # ifndef fileno
    34    /* kludge: inmos forgot fileno */
    34    /* kludge: inmos forgot fileno */
    35 #  define fileno(f)     ((f)->__file)
    35 #  define fileno(f)     ((f)->__file)
    36 # endif 
    36 # endif
    37 
    37 
    38 #else /* not transputer */
    38 #else /* not transputer */
    39 
    39 
    40 # include <sys/types.h>
    40 # include <sys/types.h>
    41 # include <sys/stat.h>
    41 # include <sys/stat.h>
   186 "
   186 "
   187     This class provides access to the operating systems underlying file
   187     This class provides access to the operating systems underlying file
   188     system (i.e. its an interface to the stdio library).
   188     system (i.e. its an interface to the stdio library).
   189 
   189 
   190     Notice, that on some systems, the standard I/O library has performance
   190     Notice, that on some systems, the standard I/O library has performance
   191     problems when a file is opened for readwrite. 
   191     problems when a file is opened for readwrite.
   192     For best results, open files either readonly or writeonly.
   192     For best results, open files either readonly or writeonly.
   193 
   193 
   194     Also notice, that some OperatingSystems do not fully support
   194     Also notice, that some OperatingSystems do not fully support
   195     positioning a file stream.
   195     positioning a file stream.
   196     For example, poor VMS does not allow positioning onto arbitrary
   196     For example, poor VMS does not allow positioning onto arbitrary
   231 	newFile openWithMode:'w' attributes:#('rfm=fix' 'fsz=100').
   231 	newFile openWithMode:'w' attributes:#('rfm=fix' 'fsz=100').
   232 
   232 
   233     since all of the above is private protocol, and it is considered bad style to
   233     since all of the above is private protocol, and it is considered bad style to
   234     access these from user programs, we recommend subclassing FileStream as
   234     access these from user programs, we recommend subclassing FileStream as
   235     something like VMSFixedRecordFileStream, and redefine the instance creation
   235     something like VMSFixedRecordFileStream, and redefine the instance creation
   236     method(s) there as appropriate. 
   236     method(s) there as appropriate.
   237     This will retain VMS specifics in one place and enhance maintanability.
   237     This will retain VMS specifics in one place and enhance maintanability.
   238 "
   238 "
   239 ! !
   239 ! !
   240 
   240 
   241 !FileStream class methodsFor:'initialization'!
   241 !FileStream class methodsFor:'initialization'!
   401 
   401 
   402     newStream := self new pathName:filename.
   402     newStream := self new pathName:filename.
   403     ^ newStream openForReading.
   403     ^ newStream openForReading.
   404 
   404 
   405     "
   405     "
   406      FileStream readonlyFileNamed:'dAsGiBtEsNiChT' 
   406      FileStream readonlyFileNamed:'dAsGiBtEsNiChT'
   407     "
   407     "
   408 !
   408 !
   409 
   409 
   410 readonlyFileNamed:filename in:aDirectory
   410 readonlyFileNamed:filename in:aDirectory
   411     "return a readonly FileStream for existing file named filename, aString
   411     "return a readonly FileStream for existing file named filename, aString
   578      in earlier versions of ST/X, failed file open operations
   578      in earlier versions of ST/X, failed file open operations
   579      returned nil - now, an error is raised.
   579      returned nil - now, an error is raised.
   580      The old behavior is simulated by providing an exception
   580      The old behavior is simulated by providing an exception
   581      handler, which proceeds with nil:
   581      handler, which proceeds with nil:
   582 
   582 
   583         OpenError ignoreIn:[ 
   583 	OpenError ignoreIn:[
   584             'old code expecting nil return values on errors when doing an open'.
   584 	    'old code expecting nil return values on errors when doing an open'.
   585 
   585 
   586             ('/dasGIBtEsbeStimmtNiChT' asFilename readStream) isNil ifTrue:[
   586 	    ('/dasGIBtEsbeStimmtNiChT' asFilename readStream) isNil ifTrue:[
   587                 self warn:'open failed'.
   587 		self warn:'open failed'.
   588             ].
   588 	    ].
   589         ]
   589 	]
   590     "
   590     "
   591 
   591 
   592     LastErrorNumber := lastErrorNumber.
   592     LastErrorNumber := lastErrorNumber.
   593     ^ super openError.
   593     ^ super openError.
   594 
   594 
   607     "the sendfile() system call currently (2004-05-07) handles only descriptors that
   607     "the sendfile() system call currently (2004-05-07) handles only descriptors that
   608      support mmap-like operations as from-fd.
   608      support mmap-like operations as from-fd.
   609      Therefore, this method is reimplemented here (from ExternalStream)"
   609      Therefore, this method is reimplemented here (from ExternalStream)"
   610 
   610 
   611     outStream isExternalStream ifTrue:[
   611     outStream isExternalStream ifTrue:[
   612         pos := self position0Based.
   612 	pos := self position0Based.
   613         n := self size - pos.
   613 	n := self size - pos.
   614         nWritten := OperatingSystem 
   614 	nWritten := OperatingSystem
   615             copyFromFd:(self fileDescriptor)
   615 	    copyFromFd:(self fileDescriptor)
   616             toFd:(outStream fileDescriptor)
   616 	    toFd:(outStream fileDescriptor)
   617             startIndex:pos 
   617 	    startIndex:pos
   618             count:n.
   618 	    count:n.
   619         nWritten = n ifTrue:[
   619 	nWritten = n ifTrue:[
   620             ^ self
   620 	    ^ self
   621         ].
   621 	].
   622         nWritten > 0 ifTrue:[
   622 	nWritten > 0 ifTrue:[
   623             self position0Based:pos+nWritten.
   623 	    self position0Based:pos+nWritten.
   624         ].
   624 	].
   625     ].
   625     ].
   626     ^ super copyToEndInto:outStream.
   626     ^ super copyToEndInto:outStream.
   627 
   627 
   628     "
   628     "
   629      |in out|
   629      |in out|
   648     if (__INST(filePointer) != nil) {
   648     if (__INST(filePointer) != nil) {
   649 	do {
   649 	do {
   650 	    f = __FILEVal(__INST(filePointer));
   650 	    f = __FILEVal(__INST(filePointer));
   651 #ifdef WIN32
   651 #ifdef WIN32
   652 	    __threadErrno = 0;
   652 	    __threadErrno = 0;
   653 	    if (__INST(buffered) == true) {                             
   653 	    if (__INST(buffered) == true) {
   654 # if 0
   654 # if 0
   655 		currentPosition = STX_C_CALL1( "ftell", ftell, f);     
   655 		currentPosition = STX_C_CALL1( "ftell", ftell, f);
   656 # else
   656 # else
   657 		currentPosition = ftell(f);     
   657 		currentPosition = ftell(f);
   658 # endif
   658 # endif
   659 	    } else {                                                   
   659 	    } else {
   660 		OBJ rA = __INST(readAhead);                            
   660 		OBJ rA = __INST(readAhead);
   661 		off_t offs = 0;
   661 		off_t offs = 0;
   662 
   662 
   663 		if (rA != nil) {                                       
   663 		if (rA != nil) {
   664 		    __INST(readAhead) = nil;                           
   664 		    __INST(readAhead) = nil;
   665 		    offs = -1;
   665 		    offs = -1;
   666 		}                                                      
   666 		}
   667 # if 0
   667 # if 0
   668 		currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR); 
   668 		currentPosition = STX_C_CALL3( "lseek", lseek, fileno(f), offs, SEEK_CUR);
   669 # else
   669 # else
   670 		currentPosition = lseek(fileno(f), offs, SEEK_CUR); 
   670 		currentPosition = lseek(fileno(f), offs, SEEK_CUR);
   671 # endif
   671 # endif
   672 	    }
   672 	    }
   673 #else /* !WIN32 */
   673 #else /* !WIN32 */
   674 	    if (__INST(buffered) == true) {
   674 	    if (__INST(buffered) == true) {
   675 #ifdef _LFS_LARGEFILE
   675 #ifdef _LFS_LARGEFILE
   710     HFILE f;
   710     HFILE f;
   711     long ret;
   711     long ret;
   712     OBJ fp;
   712     OBJ fp;
   713 
   713 
   714     if ((__INST(canPosition) != false) || (newPos == __MKSMALLINT(0))) {
   714     if ((__INST(canPosition) != false) || (newPos == __MKSMALLINT(0))) {
   715         if ((fp = __INST(filePointer)) != nil) {
   715 	if ((fp = __INST(filePointer)) != nil) {
   716 
   716 
   717 #if defined(_LFS_LARGE_FILE) && !defined(WIN32)
   717 #if defined(_LFS_LARGE_FILE) && !defined(WIN32)
   718 # define FSEEK fseeko
   718 # define FSEEK fseeko
   719             off_t nP;
   719 	    off_t nP;
   720 #else
   720 #else
   721 #define FSEEK fseek
   721 #define FSEEK fseek
   722             long nP;
   722 	    long nP;
   723 #endif
   723 #endif
   724 
   724 
   725             if (__isSmallInteger(newPos)) {
   725 	    if (__isSmallInteger(newPos)) {
   726                 nP = __intVal(newPos);
   726 		nP = __intVal(newPos);
   727                 if (nP < 0) {
   727 		if (nP < 0) {
   728                     __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   728 		    __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   729                     goto getOutOfHere;
   729 		    goto getOutOfHere;
   730                 }
   730 		}
   731             } else {
   731 	    } else {
   732                 nP = __signedLongIntVal(newPos);
   732 		nP = __signedLongIntVal(newPos);
   733                 if (nP < 0) {
   733 		if (nP < 0) {
   734                     __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   734 		    __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   735                     goto getOutOfHere;
   735 		    goto getOutOfHere;
   736                 }
   736 		}
   737                 if (nP == 0) {
   737 		if (nP == 0) {
   738                     if (sizeof(nP) == 8) {
   738 		    if (sizeof(nP) == 8) {
   739                         if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
   739 			if (__signedLong64IntVal(newPos, &nP) == 0 || nP < 0) {
   740                             __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   740 			    __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   741                             goto getOutOfHere;
   741 			    goto getOutOfHere;
   742                         }
   742 			}
   743                     } else {
   743 		    } else {
   744                         __INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   744 			__INST(lastErrorNumber) = __MKSMALLINT(EINVAL);
   745                         goto getOutOfHere;
   745 			goto getOutOfHere;
   746                     }
   746 		    }
   747                 }
   747 		}
   748             }
   748 	    }
   749 
   749 
   750             f = __FILEVal(fp);
   750 	    f = __FILEVal(fp);
   751 
   751 
   752             do {
   752 	    do {
   753 #ifdef WIN32
   753 #ifdef WIN32
   754                 __threadErrno = 0;
   754 		__threadErrno = 0;
   755                 if (__INST(buffered) == true) {                                          
   755 		if (__INST(buffered) == true) {
   756                     ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);    
   756 		    ret = STX_C_CALL3( "fseek", fseek, f, nP, SEEK_SET);
   757                 } else {                                                    
   757 		} else {
   758                     __INST(readAhead) = nil;                            
   758 		    __INST(readAhead) = nil;
   759                     ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET); 
   759 		    ret = STX_C_CALL3( "lseek", lseek, fileno(f), nP, SEEK_SET);
   760                 }
   760 		}
   761 #else
   761 #else
   762                 if (__INST(buffered) == true) {
   762 		if (__INST(buffered) == true) {
   763                     ret = FSEEK(f, nP, SEEK_SET);
   763 		    ret = FSEEK(f, nP, SEEK_SET);
   764                 } else {
   764 		} else {
   765                     ret = lseek(fileno(f), nP, SEEK_SET);
   765 		    ret = lseek(fileno(f), nP, SEEK_SET);
   766                 }
   766 		}
   767 #endif
   767 #endif
   768             } while ((ret < 0) && (__threadErrno == EINTR));
   768 	    } while ((ret < 0) && (__threadErrno == EINTR));
   769             if (ret >= 0) {
   769 	    if (ret >= 0) {
   770                 __INST(position) = newPos; __STORE(self, newPos);
   770 		__INST(position) = newPos; __STORE(self, newPos);
   771                 /*
   771 		/*
   772                  * just to make certain ...
   772 		 * just to make certain ...
   773                  */
   773 		 */
   774                 __INST(hitEOF) = false;
   774 		__INST(hitEOF) = false;
   775                 RETURN ( self );
   775 		RETURN ( self );
   776             }
   776 	    }
   777             __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno);
   777 	    __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno);
   778         }
   778 	}
   779     }
   779     }
   780     getOutOfHere: ;
   780     getOutOfHere: ;
   781 #undef FSEEK
   781 #undef FSEEK
   782 %}.
   782 %}.
   783     canPosition == false ifTrue:[
   783     canPosition == false ifTrue:[
   784         "/ position by rewinding & re-reading everything up-to
   784 	"/ position by rewinding & re-reading everything up-to
   785         "/ that point.
   785 	"/ that point.
   786         ^ self slowPosition0Based:newPos
   786 	^ self slowPosition0Based:newPos
   787     ].
   787     ].
   788     lastErrorNumber notNil ifTrue:[
   788     lastErrorNumber notNil ifTrue:[
   789         (OperatingSystem errorSymbolForNumber:lastErrorNumber) == #EINVAL ifTrue:[
   789 	(OperatingSystem errorSymbolForNumber:lastErrorNumber) == #EINVAL ifTrue:[
   790             "/ invalid position
   790 	    "/ invalid position
   791             ^ self positionError
   791 	    ^ self positionError
   792         ].
   792 	].
   793         "/ assume I/O error
   793 	"/ assume I/O error
   794         ^ self ioError
   794 	^ self ioError
   795     ].
   795     ].
   796     filePointer isNil ifTrue:[^ self errorNotOpen].
   796     filePointer isNil ifTrue:[^ self errorNotOpen].
   797 
   797 
   798     rslt := self positionFile:filePointer position:newPos.
   798     rslt := self positionFile:filePointer position:newPos.
   799     rslt >= 0 ifTrue:[
   799     rslt >= 0 ifTrue:[
   800         position := newPos.
   800 	position := newPos.
   801     ] ifFalse:[
   801     ] ifFalse:[
   802         hitEOF := true.
   802 	hitEOF := true.
   803     ]
   803     ]
   804 !
   804 !
   805 
   805 
   806 setToEnd
   806 setToEnd
   807     "set the read/write position in the file to be at the end of the file"
   807     "set the read/write position in the file to be at the end of the file"
   814 	f = __FILEVal(__INST(filePointer));
   814 	f = __FILEVal(__INST(filePointer));
   815 	__INST(position) = nil;    /* i.e. unknown */
   815 	__INST(position) = nil;    /* i.e. unknown */
   816 	do {
   816 	do {
   817 #ifdef WIN32
   817 #ifdef WIN32
   818 	    __threadErrno = 0;
   818 	    __threadErrno = 0;
   819 	    if (__INST(buffered) == true) {                                            
   819 	    if (__INST(buffered) == true) {
   820 		ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END);    
   820 		ret = STX_C_CALL3( "fseek", fseek, f, 0L, SEEK_END);
   821 	    } else {                                                   
   821 	    } else {
   822 		__INST(readAhead) = nil;                           
   822 		__INST(readAhead) = nil;
   823 		ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END);
   823 		ret = STX_C_CALL3( "lseek", lseek, fileno(f), 0L, SEEK_END);
   824 	    }
   824 	    }
   825 #else
   825 #else
   826 	    if (__INST(buffered) == true) {
   826 	    if (__INST(buffered) == true) {
   827 #ifdef _LFS_LARGE_FILE
   827 #ifdef _LFS_LARGE_FILE
   828 		ret = fseeko(f, (off_t)0, SEEK_END);
   828 		ret = fseeko(f, (off_t)0, SEEK_END);
   829 #else                
   829 #else
   830 		ret = fseek(f, 0L, SEEK_END);
   830 		ret = fseek(f, 0L, SEEK_END);
   831 #endif
   831 #endif
   832 	    } else {
   832 	    } else {
   833 		ret = lseek(fileno(f), (off_t)0, SEEK_END);
   833 		ret = lseek(fileno(f), (off_t)0, SEEK_END);
   834 	    }
   834 	    }
   922     "low level close - may be redefined in subclasses.
   922     "low level close - may be redefined in subclasses.
   923      Don't send this message, send #close instead"
   923      Don't send this message, send #close instead"
   924 
   924 
   925     super closeFile.
   925     super closeFile.
   926     removeOnClose == true ifTrue:[
   926     removeOnClose == true ifTrue:[
   927         pathName asFilename remove.
   927 	pathName asFilename remove.
   928     ]
   928     ]
   929 
   929 
   930     "Created: / 13.8.1998 / 12:11:22 / cg"
   930     "Created: / 13.8.1998 / 12:11:22 / cg"
   931 ! !
   931 ! !
   932 
   932 
   948     didWrite := true.
   948     didWrite := true.
   949     ^ self openWithMode:WriteMode
   949     ^ self openWithMode:WriteMode
   950 !
   950 !
   951 
   951 
   952 openFile:pathName withMode:openmode attributes:attributeSpec
   952 openFile:pathName withMode:openmode attributes:attributeSpec
   953     "open the file; 
   953     "open the file;
   954      openmode is the string defining the way to open as defined by the stdio library
   954      openmode is the string defining the way to open as defined by the stdio library
   955      (i.e. the 2nd fopen argument).
   955      (i.e. the 2nd fopen argument).
   956 
   956 
   957      attributeSpec is an additional argument, only used with VMS - it allows a file to
   957      attributeSpec is an additional argument, only used with VMS - it allows a file to
   958      be created as fixedRecord, variableRecord, streamLF, streamCR, ...
   958      be created as fixedRecord, variableRecord, streamLF, streamCR, ...
   967     |wasBlocked|
   967     |wasBlocked|
   968 
   968 
   969 %{
   969 %{
   970     HFILE f;
   970     HFILE f;
   971     HFILE fopen();
   971     HFILE fopen();
   972     OBJ fp;
       
   973     int pass = 0;
   972     int pass = 0;
   974 
   973 
   975 retry:
   974 retry:
   976     if (__isNonNilObject(pathName) && (__qClass(pathName)==String)) {
   975     if (__isNonNilObject(pathName) && (__qClass(pathName)==String)) {
   977 #ifdef __VMS__
   976 #ifdef __VMS__
   978         do {
   977 	do {
   979             /*
   978 	    /*
   980              * allow passing additional RMS arguments.
   979 	     * allow passing additional RMS arguments.
   981              * stupid: DEC does not seem to offer an interface for passing a char **.
   980 	     * stupid: DEC does not seem to offer an interface for passing a char **.
   982              */
   981 	     */
   983             __threadErrno = 0;
   982 	    __threadErrno = 0;
   984 
   983 
   985             {
   984 	    {
   986                 if (__isArray(attributeSpec)) {
   985 		if (__isArray(attributeSpec)) {
   987                     OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
   986 		    OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
   988                     int numAttrib = 0;
   987 		    int numAttrib = 0;
   989                     int i;
   988 		    int i;
   990 
   989 
   991                     numAttrib = __arraySize(attributeSpec);
   990 		    numAttrib = __arraySize(attributeSpec);
   992                     for (i=0; i<numAttrib;i++) {
   991 		    for (i=0; i<numAttrib;i++) {
   993                         if (! __isString(ap[i])) {
   992 			if (! __isString(ap[i])) {
   994                             f = NULL;
   993 			    f = NULL;
   995                             __threadErrno = EINVAL; /* invalid argument */
   994 			    __threadErrno = EINVAL; /* invalid argument */
   996                             goto getOutOfHere;
   995 			    goto getOutOfHere;
   997                         }
   996 			}
   998                     }
   997 		    }
   999                     switch (numAttrib) {
   998 		    switch (numAttrib) {
  1000                         case 0:
   999 			case 0:
  1001                             __BEGIN_INTERRUPTABLE__
  1000 			    __BEGIN_INTERRUPTABLE__
  1002                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1001 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode));
  1003                             __END_INTERRUPTABLE__
  1002 			    __END_INTERRUPTABLE__
  1004                             break;
  1003 			    break;
  1005                         case 1:
  1004 			case 1:
  1006                             __BEGIN_INTERRUPTABLE__
  1005 			    __BEGIN_INTERRUPTABLE__
  1007                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1006 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1008                                       __stringVal(ap[0]));
  1007 				      __stringVal(ap[0]));
  1009                             __END_INTERRUPTABLE__
  1008 			    __END_INTERRUPTABLE__
  1010                             break;
  1009 			    break;
  1011                         case 2:
  1010 			case 2:
  1012                             __BEGIN_INTERRUPTABLE__
  1011 			    __BEGIN_INTERRUPTABLE__
  1013                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1012 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1014                                       __stringVal(ap[0]), __stringVal(ap[1]));
  1013 				      __stringVal(ap[0]), __stringVal(ap[1]));
  1015                             __END_INTERRUPTABLE__
  1014 			    __END_INTERRUPTABLE__
  1016                             break;
  1015 			    break;
  1017                         case 3:
  1016 			case 3:
  1018                             __BEGIN_INTERRUPTABLE__
  1017 			    __BEGIN_INTERRUPTABLE__
  1019                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1018 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1020                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1019 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
  1021                             __END_INTERRUPTABLE__
  1020 			    __END_INTERRUPTABLE__
  1022                             break;
  1021 			    break;
  1023                         case 4:
  1022 			case 4:
  1024                             __BEGIN_INTERRUPTABLE__
  1023 			    __BEGIN_INTERRUPTABLE__
  1025                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1024 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1026                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1025 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1027                                       __stringVal(ap[3]));
  1026 				      __stringVal(ap[3]));
  1028                             __END_INTERRUPTABLE__
  1027 			    __END_INTERRUPTABLE__
  1029                             break;
  1028 			    break;
  1030                         case 5:
  1029 			case 5:
  1031                             __BEGIN_INTERRUPTABLE__
  1030 			    __BEGIN_INTERRUPTABLE__
  1032                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1031 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1033                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1032 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1034                                       __stringVal(ap[3]), __stringVal(ap[4]));
  1033 				      __stringVal(ap[3]), __stringVal(ap[4]));
  1035                             __END_INTERRUPTABLE__
  1034 			    __END_INTERRUPTABLE__
  1036                             break;
  1035 			    break;
  1037                         case 6:
  1036 			case 6:
  1038                             __BEGIN_INTERRUPTABLE__
  1037 			    __BEGIN_INTERRUPTABLE__
  1039                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1038 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1040                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1039 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1041                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1040 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
  1042                             __END_INTERRUPTABLE__
  1041 			    __END_INTERRUPTABLE__
  1043                             break;
  1042 			    break;
  1044                         case 7:
  1043 			case 7:
  1045                             __BEGIN_INTERRUPTABLE__
  1044 			    __BEGIN_INTERRUPTABLE__
  1046                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1045 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1047                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1046 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1048                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1047 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1049                                       __stringVal(ap[6]));
  1048 				      __stringVal(ap[6]));
  1050                             __END_INTERRUPTABLE__
  1049 			    __END_INTERRUPTABLE__
  1051                             break;
  1050 			    break;
  1052                         case 8:
  1051 			case 8:
  1053                             __BEGIN_INTERRUPTABLE__
  1052 			    __BEGIN_INTERRUPTABLE__
  1054                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1053 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1055                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1054 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1056                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1055 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1057                                       __stringVal(ap[6]), __stringVal(ap[7]));
  1056 				      __stringVal(ap[6]), __stringVal(ap[7]));
  1058                             __END_INTERRUPTABLE__
  1057 			    __END_INTERRUPTABLE__
  1059                             break;
  1058 			    break;
  1060                         case 9:
  1059 			case 9:
  1061                             __BEGIN_INTERRUPTABLE__
  1060 			    __BEGIN_INTERRUPTABLE__
  1062                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1061 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1063                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1062 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1064                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1063 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1065                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1064 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1066                             __END_INTERRUPTABLE__
  1065 			    __END_INTERRUPTABLE__
  1067                             break;
  1066 			    break;
  1068                         case 10:
  1067 			case 10:
  1069                             __BEGIN_INTERRUPTABLE__
  1068 			    __BEGIN_INTERRUPTABLE__
  1070                             f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1069 			    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode),
  1071                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1070 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1072                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1071 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1073                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1072 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1074                                       __stringVal(ap[9]));
  1073 				      __stringVal(ap[9]));
  1075                             __END_INTERRUPTABLE__
  1074 			    __END_INTERRUPTABLE__
  1076                             break;
  1075 			    break;
  1077                         default:
  1076 			default:
  1078                             f = NULL;
  1077 			    f = NULL;
  1079                             __threadErrno = E2BIG; /* too many args */
  1078 			    __threadErrno = E2BIG; /* too many args */
  1080                             goto getOutOfHere;
  1079 			    goto getOutOfHere;
  1081                     }
  1080 		    }
  1082                 } else if (attributeSpec != nil) {
  1081 		} else if (attributeSpec != nil) {
  1083                     f = NULL;
  1082 		    f = NULL;
  1084                     __threadErrno = EINVAL; /* invalid argument */
  1083 		    __threadErrno = EINVAL; /* invalid argument */
  1085                     goto getOutOfHere;
  1084 		    goto getOutOfHere;
  1086                 } else {
  1085 		} else {
  1087                     /*
  1086 		    /*
  1088                      * create file as sequential streamLF by default.
  1087 		     * create file as sequential streamLF by default.
  1089                      */
  1088 		     */
  1090                     __BEGIN_INTERRUPTABLE__
  1089 		    __BEGIN_INTERRUPTABLE__
  1091                     f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1090 		    f = fopen((char *)__stringVal(pathName), (char *)__stringVal(openmode), "rfm=stmlf");
  1092                     __END_INTERRUPTABLE__
  1091 		    __END_INTERRUPTABLE__
  1093                 }
  1092 		}
  1094             }
  1093 	    }
  1095         } while ((f == NULL) && (__threadErrno == EINTR));
  1094 	} while ((f == NULL) && (__threadErrno == EINTR));
  1096 
  1095 
  1097 #else /* not VMS */
  1096 #else /* not VMS */
  1098 
  1097 
  1099 # ifdef WIN32
  1098 # ifdef WIN32
  1100         {
  1099 	{
  1101             char _aPathName[MAXPATHLEN];
  1100 	    char _aPathName[MAXPATHLEN];
  1102             char _openMode[64];
  1101 	    char _openMode[64];
  1103 
  1102 
  1104             strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1103 	    strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
  1105             strncpy(_openMode, __stringVal(openmode), sizeof(_openMode)-1); _openMode[sizeof(_openMode)-1] = '\0';
  1104 	    strncpy(_openMode, __stringVal(openmode), sizeof(_openMode)-1); _openMode[sizeof(_openMode)-1] = '\0';
  1106             do {
  1105 	    do {
  1107                 __threadErrno = 0;
  1106 		__threadErrno = 0;
  1108                 f = STX_C_CALL2( "fopen", fopen, _aPathName, _openMode);
  1107 		f = STX_C_CALL2( "fopen", fopen, _aPathName, _openMode);
  1109                 if (__threadErrno == EINTR) {
  1108 		if (__threadErrno == EINTR) {
  1110                     f = NULL;
  1109 		    f = NULL;
  1111                 }
  1110 		}
  1112             } while ((f == NULL) && (__threadErrno == EINTR));
  1111 	    } while ((f == NULL) && (__threadErrno == EINTR));
  1113         }
  1112 	}
  1114 # else /* not WIN32 */
  1113 # else /* not WIN32 */
  1115 
  1114 
  1116         do {
  1115 	do {
  1117             __BEGIN_INTERRUPTABLE__
  1116 	    __BEGIN_INTERRUPTABLE__
  1118 #  ifdef LINUX
  1117 #  ifdef LINUX
  1119             /* 
  1118 	    /*
  1120              * LINUX may ret a non-NULL f even when interrupted.
  1119 	     * LINUX may ret a non-NULL f even when interrupted.
  1121              * Therefore, check errno and fake a null-ret.
  1120 	     * Therefore, check errno and fake a null-ret.
  1122              */
  1121 	     */
  1123             __threadErrno = 0;
  1122 	    __threadErrno = 0;
  1124             f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode));
  1123 	    f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode));
  1125             if (__threadErrno == EINTR)
  1124 	    if (__threadErrno == EINTR)
  1126                 f = NULL;
  1125 		f = NULL;
  1127 #  else /* not LINUX */
  1126 #  else /* not LINUX */
  1128             f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode));
  1127 	    f = fopen((char *) __stringVal(pathName), (char *) __stringVal(openmode));
  1129 #  endif /* not LINUX */
  1128 #  endif /* not LINUX */
  1130             __END_INTERRUPTABLE__
  1129 	    __END_INTERRUPTABLE__
  1131         } while ((f == NULL) && (__threadErrno == EINTR));
  1130 	} while ((f == NULL) && (__threadErrno == EINTR));
  1132 
  1131 
  1133 # endif /* not WIN32 */
  1132 # endif /* not WIN32 */
  1134 #endif /* not VMS */
  1133 #endif /* not VMS */
  1135 
  1134 
  1136         if (f == NULL) {
  1135 	if (f == NULL) {
  1137             /*
  1136 	    /*
  1138              * If no filedescriptors available, try to finalize
  1137 	     * If no filedescriptors available, try to finalize
  1139              * possibly collected fd's and try again.
  1138 	     * possibly collected fd's and try again.
  1140              */
  1139 	     */
  1141             if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) {
  1140 	    if (pass == 0 && (__threadErrno == ENFILE || __threadErrno == EMFILE)) {
  1142                 pass = 1;
  1141 		pass = 1;
  1143                 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1142 		__SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1144                 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1143 		__SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1145                 goto retry;
  1144 		goto retry;
  1146             }
  1145 	    }
  1147         getOutOfHere: ;
  1146 	getOutOfHere: ;
  1148             __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno);
  1147 	    __INST(lastErrorNumber) = __MKSMALLINT(__threadErrno);
  1149             __INST(position) = nil;
  1148 	    __INST(position) = nil;
  1150         } else {
  1149 	} else {
  1151 #ifdef __VMS__
  1150 #ifdef __VMS__
  1152             /*
  1151 	    /*
  1153              * check to see if this is positionable ...
  1152 	     * check to see if this is positionable ...
  1154              */
  1153 	     */
  1155             __INST(canPosition) = false;
  1154 	    __INST(canPosition) = false;
  1156 # ifndef _POSIX_C_SOURCE
  1155 # ifndef _POSIX_C_SOURCE
  1157             {
  1156 	    {
  1158                 struct stat statBuffer;
  1157 		struct stat statBuffer;
  1159 
  1158 
  1160                 if (fstat(fileno(f), &statBuffer) >= 0) {
  1159 		if (fstat(fileno(f), &statBuffer) >= 0) {
  1161                     switch (statBuffer.st_fab_rfm) {
  1160 		    switch (statBuffer.st_fab_rfm) {
  1162                         case FAB$C_UDF: /* undefined (also stream binary)   */
  1161 			case FAB$C_UDF: /* undefined (also stream binary)   */
  1163                         case FAB$C_VAR: /* variable length records          */
  1162 			case FAB$C_VAR: /* variable length records          */
  1164                         case FAB$C_VFC: /* variable fixed control           */
  1163 			case FAB$C_VFC: /* variable fixed control           */
  1165                         case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */
  1164 			case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */
  1166                         default:
  1165 			default:
  1167                             __INST(canPosition) = false;
  1166 			    __INST(canPosition) = false;
  1168                             break;
  1167 			    break;
  1169 
  1168 
  1170                         case FAB$C_FIX: /* fixed length records             */
  1169 			case FAB$C_FIX: /* fixed length records             */
  1171                         case FAB$C_STMLF: /* LF stream (valid only for sequential> */
  1170 			case FAB$C_STMLF: /* LF stream (valid only for sequential> */
  1172                         case FAB$C_STMCR: /* CR stream (valid only for sequential> */
  1171 			case FAB$C_STMCR: /* CR stream (valid only for sequential> */
  1173                             __INST(canPosition) = true;
  1172 			    __INST(canPosition) = true;
  1174                             break;
  1173 			    break;
  1175                     }
  1174 		    }
  1176                 }
  1175 		}
  1177             }
  1176 	    }
  1178 # endif 
  1177 # endif
  1179 #else /* not VMS */
  1178 #else /* not VMS */
  1180             __INST(canPosition) = true;
  1179 	    __INST(canPosition) = true;
  1181 #endif /* poor VMS */
  1180 #endif /* poor VMS */
  1182 
  1181 
  1183             if (@global(FileOpenTrace) == true) {
  1182 	    if (@global(FileOpenTrace) == true) {
  1184                 fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f);
  1183 		fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f);
  1185             }
  1184 	    }
  1186             if (f != NULL) {
  1185 	    if (f != NULL) {
  1187                 wasBlocked = __BLOCKINTERRUPTS();
  1186 		OBJ fp;
  1188                 __INST(filePointer) = fp = __MKOBJ((INT)f); __STORE(self, fp);
  1187 
  1189             }
  1188 		wasBlocked = __BLOCKINTERRUPTS();
  1190         }
  1189 #if 0
       
  1190 		// The original code was:
       
  1191 		__INST(filePointer) = fp = __MKOBJ((INT)f); __STORE(self, fp);
       
  1192 		// but for that, gcc generates wrong code, which loads self (volatile) into
       
  1193 		// a register (bp), then calls __MKOBJ, then stores indirect bp.
       
  1194 		// That is wrong if a scavenge occurs in MKOBJ, as bp is now still pointing to the old
       
  1195 		// object.
       
  1196 #else
       
  1197 		fp = __MKOBJ((INT)f);
       
  1198 		__INST(filePointer) = fp;
       
  1199 		__STORE(self, fp);
       
  1200 #endif
       
  1201 	    }
       
  1202 	}
  1191     }
  1203     }
  1192 %}.
  1204 %}.
  1193     position := ZeroPosition.
  1205     position := ZeroPosition.
  1194     filePointer notNil ifTrue:[
  1206     filePointer notNil ifTrue:[
  1195         Lobby register:self.
  1207 	Lobby register:self.
  1196         wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts].
  1208 	wasBlocked == false ifTrue:[OperatingSystem unblockInterrupts].
  1197     ].
  1209     ].
  1198     ^ filePointer
  1210     ^ filePointer
  1199 !
  1211 !
  1200 
  1212 
  1201 openForAppending
  1213 openForAppending
  1202     "open the file for writeonly appending to the end.
  1214     "open the file for writeonly appending to the end.
  1203      If the file does not exist its an error, raise OpenError; 
  1215      If the file does not exist its an error, raise OpenError;
  1204      otherwise return the receiver."
  1216      otherwise return the receiver."
  1205 
  1217 
  1206     mode := #writeonly.
  1218     mode := #writeonly.
  1207     didWrite := true.
  1219     didWrite := true.
  1208     ^ self openWithMode:AppendMode
  1220     ^ self openWithMode:AppendMode
  1209 !
  1221 !
  1210 
  1222 
  1211 openForReadWrite
  1223 openForReadWrite
  1212     "open the file for read/write.
  1224     "open the file for read/write.
  1213      If the file does not exist its an error, raise OpenError; 
  1225      If the file does not exist its an error, raise OpenError;
  1214      otherwise return the receiver."
  1226      otherwise return the receiver."
  1215 
  1227 
  1216     mode := #readwrite.
  1228     mode := #readwrite.
  1217     ^ self openWithMode:ReadWriteMode
  1229     ^ self openWithMode:ReadWriteMode
  1218 !
  1230 !
  1219 
  1231 
  1220 openForReading
  1232 openForReading
  1221     "open the file for readonly.
  1233     "open the file for readonly.
  1222      If the file does not exist its an error, raise OpenError; 
  1234      If the file does not exist its an error, raise OpenError;
  1223      otherwise return the receiver."
  1235      otherwise return the receiver."
  1224 
  1236 
  1225     mode := #readonly.
  1237     mode := #readonly.
  1226     didWrite := false.
  1238     didWrite := false.
  1227     ^ self openWithMode:ReadMode
  1239     ^ self openWithMode:ReadMode
  1228 !
  1240 !
  1229 
  1241 
  1230 openForWriting
  1242 openForWriting
  1231     "open the file writeonly. The contents of the file is preserved.
  1243     "open the file writeonly. The contents of the file is preserved.
  1232      If the file does not exist its an error, raise OpenError; 
  1244      If the file does not exist its an error, raise OpenError;
  1233      otherwise return the receiver."
  1245      otherwise return the receiver."
  1234 
  1246 
  1235     mode := #writeonly.
  1247     mode := #writeonly.
  1236     didWrite := true.
  1248     didWrite := true.
  1237     "we must not truncate the file!! So do not use WriteMode"
  1249     "we must not truncate the file!! So do not use WriteMode"
  1243      openmode is the string defining the way to open as defined by the stdio library
  1255      openmode is the string defining the way to open as defined by the stdio library
  1244      (i.e. the 2nd fopen argument).
  1256      (i.e. the 2nd fopen argument).
  1245 
  1257 
  1246      This is a private entry, but maybe useful to open a file in a special mode,
  1258      This is a private entry, but maybe useful to open a file in a special mode,
  1247      which is proprietrary to the operatingSystem."
  1259      which is proprietrary to the operatingSystem."
  1248      
  1260 
  1249     ^ self openWithMode:openmode attributes:nil
  1261     ^ self openWithMode:openmode attributes:nil
  1250 !
  1262 !
  1251 
  1263 
  1252 openWithMode:openmode attributes:attributeSpec
  1264 openWithMode:openmode attributes:attributeSpec
  1253     "open the file; 
  1265     "open the file;
  1254      openmode is the string defining the way to open as defined by the stdio library
  1266      openmode is the string defining the way to open as defined by the stdio library
  1255      (i.e. the 2nd fopen argument).
  1267      (i.e. the 2nd fopen argument).
  1256 
  1268 
  1257      attributeSpec is an additional argument, only used with VMS - it allows a file to
  1269      attributeSpec is an additional argument, only used with VMS - it allows a file to
  1258      be created as fixedRecord, variableRecord, streamLF, streamCR, ...
  1270      be created as fixedRecord, variableRecord, streamLF, streamCR, ...
  1266 
  1278 
  1267     filePointer notNil ifTrue:[^ self errorAlreadyOpen].
  1279     filePointer notNil ifTrue:[^ self errorAlreadyOpen].
  1268 
  1280 
  1269     filePointer := self openFile:pathName withMode:openmode attributes:attributeSpec.
  1281     filePointer := self openFile:pathName withMode:openmode attributes:attributeSpec.
  1270     filePointer isNil ifTrue:[
  1282     filePointer isNil ifTrue:[
  1271         "
  1283 	"
  1272          the open failed for some reason ...
  1284 	 the open failed for some reason ...
  1273         "
  1285 	"
  1274         ^ self openError
  1286 	^ self openError
  1275     ].
  1287     ].
  1276     position := ZeroPosition.
  1288     position := ZeroPosition.
  1277     buffered isNil ifTrue:[
  1289     buffered isNil ifTrue:[
  1278         buffered := true.       "default is buffered"
  1290 	buffered := true.       "default is buffered"
  1279     ].
  1291     ].
  1280 !
  1292 !
  1281 
  1293 
  1282 pathName:filename
  1294 pathName:filename
  1283     "set the pathname"
  1295     "set the pathname"
  1298 reOpen
  1310 reOpen
  1299     "USERS WILL NEVER INVOKE THIS METHOD
  1311     "USERS WILL NEVER INVOKE THIS METHOD
  1300      sent after snapin to reopen streams."
  1312      sent after snapin to reopen streams."
  1301 
  1313 
  1302     filePointer notNil ifTrue:[
  1314     filePointer notNil ifTrue:[
  1303         "it was open, when snapped-out"
  1315 	"it was open, when snapped-out"
  1304         filePointer := nil.
  1316 	filePointer := nil.
  1305         Lobby unregister:self.
  1317 	Lobby unregister:self.
  1306         pathName isNil ifTrue:[
  1318 	pathName isNil ifTrue:[
  1307             ^ self.
  1319 	    ^ self.
  1308         ].
  1320 	].
  1309         [
  1321 	[
  1310             |oldPos|
  1322 	    |oldPos|
  1311 
  1323 
  1312             "should take care of appending files and open them for
  1324 	    "should take care of appending files and open them for
  1313              append / position them to the end"
  1325 	     append / position them to the end"
  1314 
  1326 
  1315             oldPos := position.
  1327 	    oldPos := position.
  1316 
  1328 
  1317             mode == #readonly ifTrue: [
  1329 	    mode == #readonly ifTrue: [
  1318                 self openForReading
  1330 		self openForReading
  1319             ] ifFalse:[mode == #writeonly ifTrue: [
  1331 	    ] ifFalse:[mode == #writeonly ifTrue: [
  1320                 self openForWriting.
  1332 		self openForWriting.
  1321             ] ifFalse:[
  1333 	    ] ifFalse:[
  1322                 self openForReadWrite.
  1334 		self openForReadWrite.
  1323             ]].
  1335 	    ]].
  1324 
  1336 
  1325             oldPos notNil ifTrue:[
  1337 	    oldPos notNil ifTrue:[
  1326                 self position:oldPos.
  1338 		self position:oldPos.
  1327             ]
  1339 	    ]
  1328         ] on:OpenError do:[:ex|
  1340 	] on:OpenError do:[:ex|
  1329             "this happens, if after a restart, 
  1341 	    "this happens, if after a restart,
  1330              the file is no longer present or accessable ..."
  1342 	     the file is no longer present or accessable ..."
  1331 
  1343 
  1332             (self class name , ' [warning]: could not reopen file: ', pathName) errorPrintCR.
  1344 	    (self class name , ' [warning]: could not reopen file: ', pathName) errorPrintCR.
  1333         ]. 
  1345 	].
  1334     ]
  1346     ]
  1335 
  1347 
  1336     "Modified: 10.1.1997 / 17:50:51 / cg"
  1348     "Modified: 10.1.1997 / 17:50:51 / cg"
  1337 !
  1349 !
  1338 
  1350 
  1427 ! !
  1439 ! !
  1428 
  1440 
  1429 !FileStream class methodsFor:'documentation'!
  1441 !FileStream class methodsFor:'documentation'!
  1430 
  1442 
  1431 version
  1443 version
  1432     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.115 2004-09-29 13:42:29 stefan Exp $'
  1444     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.116 2004-11-09 17:26:59 cg Exp $'
  1433 ! !
  1445 ! !
  1434 
  1446 
  1435 FileStream initialize!
  1447 FileStream initialize!