FileStream.st
changeset 4910 33b0edbb1920
parent 4907 0b09209a95c8
child 5120 13143fbcbdf8
equal deleted inserted replaced
4909:bc474f9c0180 4910:33b0edbb1920
    26 
    26 
    27 #include <errno.h>
    27 #include <errno.h>
    28 #define _ERRNO_H_INCLUDED_
    28 #define _ERRNO_H_INCLUDED_
    29 
    29 
    30 #ifdef transputer
    30 #ifdef transputer
       
    31 
    31 # include <iocntrl.h>
    32 # include <iocntrl.h>
    32 # ifndef fileno
    33 # ifndef fileno
    33    /* kludge: inmos forgot fileno */
    34    /* kludge: inmos forgot fileno */
    34 #  define fileno(f)     ((f)->__file)
    35 #  define fileno(f)     ((f)->__file)
    35 # endif
    36 # endif
    36 #else
    37 
       
    38 #else /* not transputer */
       
    39 
    37 # include <sys/types.h>
    40 # include <sys/types.h>
    38 # include <sys/stat.h>
    41 # include <sys/stat.h>
    39 #endif
    42 
       
    43 #endif /* not transputer */
    40 
    44 
    41 #ifdef hpux
    45 #ifdef hpux
    42 # define fileno(f)      ((f->__fileH << 8) | (f->__fileL))
    46 # define fileno(f)      ((f->__fileH << 8) | (f->__fileL))
    43 #endif
    47 #endif
    44 
    48 
    70  */
    74  */
    71 # include <rms.h>
    75 # include <rms.h>
    72 #endif
    76 #endif
    73 
    77 
    74 #ifndef WIN32
    78 #ifndef WIN32
    75  extern long ftell(), lseek();
    79   extern long ftell(), lseek();
       
    80 # define HFILE FILE *
       
    81 
    76 #endif
    82 #endif
       
    83 
       
    84 #ifdef WIN32
       
    85 # define NO_STDIO
       
    86 # ifdef i386
       
    87 #  define _X86_
       
    88 # endif
       
    89 
       
    90 # undef INT
       
    91 # undef Array
       
    92 # undef Number
       
    93 # undef Method
       
    94 # undef Point
       
    95 # undef Rectangle
       
    96 # undef Block
       
    97 # undef Time
       
    98 # undef Date
       
    99 
       
   100 # define NOATOM
       
   101 # define NOGDICAPMASKS
       
   102 # define NOMETAFILE
       
   103 # define NOMINMAX
       
   104 //# define NOOPENFILE
       
   105 # define NOSOUND
       
   106 # define NOWH
       
   107 //# define NOCOMM
       
   108 # define NOKANJI
       
   109 # define NOCRYPT
       
   110 //# define NOMCX
       
   111 # define WIN32_LEAN_AND_MEAN
       
   112 
       
   113 # include <windows.h>
       
   114 # include <winsock.h> /* */
       
   115 
       
   116 # if !defined(__BORLANDC__)
       
   117 #  define stat _stat
       
   118 # endif
       
   119 
       
   120 # ifdef __DEF_Array
       
   121 #  define Array __DEF_Array
       
   122 # endif
       
   123 # ifdef __DEF_Number
       
   124 #  define Number __DEF_Number
       
   125 # endif
       
   126 # ifdef __DEF_Method
       
   127 #  define Method __DEF_Method
       
   128 # endif
       
   129 # ifdef __DEF_Point
       
   130 #  define Point __DEF_Point
       
   131 # endif
       
   132 # ifdef __DEF_Block
       
   133 #  define Block __DEF_Block
       
   134 # endif
       
   135 # ifdef __DEF_Time
       
   136 #  define Time __DEF_Time
       
   137 # endif
       
   138 # ifdef __DEF_Date
       
   139 #  define Date __DEF_Date
       
   140 # endif
       
   141 
       
   142 # define INT int
       
   143 
       
   144 # ifdef NO_STDIO
       
   145 
       
   146 /*#  define HFILE HANDLE*/
       
   147 #  define HFILE FILE *
       
   148 //#  define fileno(f) f
       
   149 
       
   150 #  define TELL(currentPosition,f,buffered)                       \
       
   151     if (buffered) {                                             \
       
   152 	currentPosition = ftell(f);                             \
       
   153     } else {                                                    \
       
   154 	OBJ rA = __INST(readAhead);                             \
       
   155 	if (rA != nil) {                                        \
       
   156 	    __INST(readAhead) = nil;                            \
       
   157 	    currentPosition = lseek(fileno(f), -1L, SEEK_CUR);  \
       
   158 	} else {                                                \
       
   159 	  currentPosition = lseek(fileno(f), 0L, SEEK_CUR);     \
       
   160 	}                                                       \
       
   161     }
       
   162 
       
   163 #  define SEEK(ret,f,nP,buffered)                        \
       
   164     if (buffered) {                                     \
       
   165 	ret = fseek(f, nP, SEEK_SET);                   \
       
   166     } else {                                            \
       
   167 	OBJ rA = __INST(readAhead);                     \
       
   168 	if (rA != nil) {                                \
       
   169 	    __INST(readAhead) = nil;                    \
       
   170 	}                                               \
       
   171 	ret = lseek(fileno(f), nP, SEEK_SET);           \
       
   172     }
       
   173 
       
   174 #  define TOEND(ret,f,buffered)                          \
       
   175     if (buffered) {                                     \
       
   176 	ret = fseek(f, 0L, SEEK_END);                   \
       
   177     } else {                                            \
       
   178 	OBJ rA = __INST(readAhead);                     \
       
   179 	if (rA != nil) {                                \
       
   180 	    __INST(readAhead) = nil;                    \
       
   181 	}                                               \
       
   182 	ret = lseek(fileno(f), 0L, SEEK_END);           \
       
   183     }
       
   184 
       
   185 # else /* use STDIO */
       
   186 
       
   187 #  define HFILE FILE *
       
   188 
       
   189 #  define TELL(currentPosition,f,buffered)                 \
       
   190     if (buffered) {                                       \
       
   191 	currentPosition = ftell(f);                       \
       
   192     } else {                                              \
       
   193 	currentPosition = lseek(fileno(f), 0L, SEEK_CUR); \
       
   194     }
       
   195 
       
   196 #  define SEEK(ret,f,nP,buffered)                        \
       
   197     if (buffered) {                                     \
       
   198 	ret = fseek(f, nP, SEEK_SET);                   \
       
   199     } else {                                            \
       
   200 	ret = lseek(fileno(f), nP, SEEK_SET);           \
       
   201     }
       
   202 
       
   203 #  define TOEND(ret,f,buffered)                          \
       
   204     if (buffered) {                                     \
       
   205 	ret = fseek(f, 0L, SEEK_END);                   \
       
   206     } else {                                            \
       
   207 	ret = lseek(fileno(f), 0L, SEEK_END);           \
       
   208     }
       
   209 
       
   210   extern long ftell(), lseek();
       
   211 # endif /* use STDIO */
       
   212 
       
   213 #endif /* WIN32 */
    77 
   214 
    78 /*
   215 /*
    79  * on some systems errno is a macro ... check for it here
   216  * on some systems errno is a macro ... check for it here
    80  */
   217  */
    81 #ifndef errno
   218 #ifndef errno
   119     Therefore, the instance variable canPosition is set according to
   256     Therefore, the instance variable canPosition is set according to
   120     this and an error is raised, if a position: is attemted.
   257     this and an error is raised, if a position: is attemted.
   121     I know, this is ugly, but what else could we do ?
   258     I know, this is ugly, but what else could we do ?
   122 
   259 
   123     [instance variables:]
   260     [instance variables:]
   124 	pathName	<String>	the files path (if known)
   261 	pathName        <String>        the files path (if known)
   125 	canPosition	<Boolean>	positionable - read above comment
   262 	canPosition     <Boolean>       positionable - read above comment
   126 
   263 
   127     [author:]
   264     [author:]
   128 	Claus Gittinger
   265 	Claus Gittinger
   129 
   266 
   130     [see also:]
   267     [see also:]
   159 
   296 
   160 !FileStream class methodsFor:'initialization'!
   297 !FileStream class methodsFor:'initialization'!
   161 
   298 
   162 initialize
   299 initialize
   163     OpenErrorSignal isNil ifTrue:[
   300     OpenErrorSignal isNil ifTrue:[
   164         "/
   301 	"/
   165         "/ this is temporary - for now allow an openError to
   302 	"/ this is temporary - for now allow an openError to
   166         "/ be unhandled and proceed by returning a nil from the
   303 	"/ be unhandled and proceed by returning a nil from the
   167         "/ stream creation method.
   304 	"/ stream creation method.
   168         "/ In the future, this will be a hard signal.
   305 	"/ In the future, this will be a hard signal.
   169         "/
   306 	"/
   170         OpenErrorSignal := QuerySignal new.
   307 	OpenErrorSignal := QuerySignal new.
   171         OpenErrorSignal parent:(super openErrorSignal) mayProceed:true.
   308 	OpenErrorSignal parent:(super openErrorSignal) mayProceed:true.
   172         OpenErrorSignal nameClass:self message:#openErrorSignal.
   309 	OpenErrorSignal nameClass:self message:#openErrorSignal.
   173         OpenErrorSignal notifierString:'open error'.
   310 	OpenErrorSignal notifierString:'open error'.
   174 
   311 
   175         UserInitiatedFileSaveQuerySignal := QuerySignal new defaultAnswer:true.
   312 	UserInitiatedFileSaveQuerySignal := QuerySignal new defaultAnswer:true.
   176         UserInitiatedFileSaveQuerySignal nameClass:self message:#userInitiatedFileSaveQuerySignal.
   313 	UserInitiatedFileSaveQuerySignal nameClass:self message:#userInitiatedFileSaveQuerySignal.
   177     ]
   314     ]
   178 
   315 
   179     "Modified: 8.10.1997 / 11:56:39 / cg"
   316     "Modified: 8.10.1997 / 11:56:39 / cg"
   180 ! !
   317 ! !
   181 
   318 
   466 closeFile
   603 closeFile
   467     "low level close - may be redefined in subclasses"
   604     "low level close - may be redefined in subclasses"
   468 
   605 
   469     super closeFile.
   606     super closeFile.
   470     removeOnClose == true ifTrue:[
   607     removeOnClose == true ifTrue:[
   471         pathName asFilename remove.
   608 	pathName asFilename remove.
   472     ]
   609     ]
   473 
   610 
   474     "Created: / 13.8.1998 / 12:11:22 / cg"
   611     "Created: / 13.8.1998 / 12:11:22 / cg"
   475 ! !
   612 ! !
   476 
   613 
   480     "return the read/write position in the file -
   617     "return the read/write position in the file -
   481      notice, in smalltalk indices start at 1 so begin of file is 1"
   618      notice, in smalltalk indices start at 1 so begin of file is 1"
   482 
   619 
   483 %{
   620 %{
   484 
   621 
   485     FILE *f;
   622     HFILE f;
   486     long currentPosition;
   623     long currentPosition;
   487 
   624 
   488     if (__INST(filePointer) != nil) {
   625     if (__INST(filePointer) != nil) {
   489 	f = __FILEVal(__INST(filePointer));
   626 	f = __FILEVal(__INST(filePointer));
   490 	do {
   627 	do {
       
   628 #ifdef WIN32
       
   629 	    TELL(currentPosition,f,__INST(buffered) == true);
       
   630 #else
   491 	    if (__INST(buffered) == true) {
   631 	    if (__INST(buffered) == true) {
   492 		currentPosition = ftell(f);
   632 		currentPosition = ftell(f);
   493 	    } else {
   633 	    } else {
   494 		currentPosition = lseek(fileno(f), 0L, SEEK_CUR);
   634 		currentPosition = lseek(fileno(f), 0L, SEEK_CUR);
   495 	    }
   635 	    }
       
   636 #endif
   496 	} while ((currentPosition < 0) && (errno == EINTR));
   637 	} while ((currentPosition < 0) && (errno == EINTR));
   497 	if (currentPosition >= 0) {
   638 	if (currentPosition >= 0) {
   498 	    /*
   639 	    /*
   499 	     * notice: Smalltalk index starts at 1
   640 	     * notice: Smalltalk index starts at 1
   500 	     */
   641 	     */
   511 position:newPos
   652 position:newPos
   512     "set the read/write position in the file"
   653     "set the read/write position in the file"
   513 
   654 
   514 %{
   655 %{
   515 
   656 
   516     FILE *f;
   657     HFILE f;
   517     long ret;
   658     long ret;
   518     OBJ fp;
   659     OBJ fp;
   519     long nP;
   660     long nP;
   520 
   661 
   521     if ((__INST(canPosition) != false) 
   662     if ((__INST(canPosition) != false) 
   522      || (newPos == __MKSMALLINT(1))) {
   663      || (newPos == __MKSMALLINT(1))) {
   523         if ((fp = __INST(filePointer)) != nil) {
   664 	if ((fp = __INST(filePointer)) != nil) {
   524 	    if (__isSmallInteger(newPos)) {
   665 	    if (__isSmallInteger(newPos)) {
   525 	        f = __FILEVal(fp);
   666 		f = __FILEVal(fp);
   526 	        nP = (long)__intVal(newPos);
   667 		nP = (long)__intVal(newPos);
   527 
   668 
   528 	        /*
   669 		/*
   529 	         * notice: Smalltalk index starts at 1
   670 		 * notice: Smalltalk index starts at 1
   530 	         */
   671 		 */
   531 	        nP--;
   672 		nP--;
   532 
   673 
   533 	        do {
   674 		do {
       
   675 #ifdef WIN32
       
   676 		    SEEK(ret,f,nP,__INST(buffered) == true);
       
   677 #else
   534 		    if (__INST(buffered) == true) {
   678 		    if (__INST(buffered) == true) {
   535 		        ret = fseek(f, nP, SEEK_SET);
   679 			ret = fseek(f, nP, SEEK_SET);
   536 		    } else {
   680 		    } else {
   537 		        ret = lseek(fileno(f), nP, SEEK_SET);
   681 			ret = lseek(fileno(f), nP, SEEK_SET);
   538 		    }
   682 		    }
   539 	        } while ((ret < 0) && (errno == EINTR));
   683 #endif
   540 	        if (ret >= 0) {
   684 		} while ((ret < 0) && (errno == EINTR));
       
   685 		if (ret >= 0) {
   541 		    __INST(position) = newPos;
   686 		    __INST(position) = newPos;
   542 		    /*
   687 		    /*
   543 		     * just to make certain ...
   688 		     * just to make certain ...
   544 		     */
   689 		     */
   545 		    __INST(hitEOF) = false;
   690 		    __INST(hitEOF) = false;
   546 		    RETURN ( self );
   691 		    RETURN ( self );
   547 	        }
   692 		}
   548 	        __INST(lastErrorNumber) = __MKSMALLINT(errno);
   693 		__INST(lastErrorNumber) = __MKSMALLINT(errno);
   549 	    }
   694 	    }
   550 	}
   695 	}
   551     }
   696     }
   552 %}.
   697 %}.
   553     canPosition == false ifTrue:[
   698     canPosition == false ifTrue:[
   569 
   714 
   570 setToEnd
   715 setToEnd
   571     "set the read/write position in the file to be at the end of the file"
   716     "set the read/write position in the file to be at the end of the file"
   572 
   717 
   573 %{
   718 %{
   574     FILE *f;
   719     HFILE f;
   575     long ret;
   720     long ret;
   576 
   721 
   577     if (__INST(filePointer) != nil) {
   722     if (__INST(filePointer) != nil) {
   578 	f = __FILEVal(__INST(filePointer));
   723 	f = __FILEVal(__INST(filePointer));
   579 	__INST(position) = nil;
   724 	__INST(position) = nil;
   580 	do {
   725 	do {
       
   726 #ifdef WIN32
       
   727 	    TOEND(ret,f,__INST(buffered) == true);
       
   728 #else
   581 	    if (__INST(buffered) == true) {
   729 	    if (__INST(buffered) == true) {
   582 		ret = fseek(f, 0L, SEEK_END);
   730 		ret = fseek(f, 0L, SEEK_END);
   583 	    } else {
   731 	    } else {
   584 		ret = lseek(fileno(f), 0L, SEEK_END);
   732 		ret = lseek(fileno(f), 0L, SEEK_END);
   585 	    }
   733 	    }
       
   734 #endif
   586 	} while ((ret < 0) && (errno == EINTR));
   735 	} while ((ret < 0) && (errno == EINTR));
   587 	if (ret >= 0) {
   736 	if (ret >= 0) {
   588 	    RETURN ( self );
   737 	    RETURN ( self );
   589 	}
   738 	}
   590 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
   739 	__INST(lastErrorNumber) = __MKSMALLINT(errno);
   599     "position the file by re-reading everything up-to newPos.
   748     "position the file by re-reading everything up-to newPos.
   600      The effect is the same as that of #position:, but its much slower.
   749      The effect is the same as that of #position:, but its much slower.
   601      This is required to reposition nonPositionable streams, such
   750      This is required to reposition nonPositionable streams, such
   602      as tape-streams or variable-record-RMS files under VMS.
   751      as tape-streams or variable-record-RMS files under VMS.
   603      Caveat:
   752      Caveat:
   604          This should really be done transparently by the stdio library."
   753 	 This should really be done transparently by the stdio library."
   605 
   754 
   606     |buffer amount|
   755     |buffer amount|
   607 
   756 
   608     self isReadable ifFalse:[
   757     self isReadable ifFalse:[
   609 	"/ sorry
   758 	"/ sorry
   612 
   761 
   613     buffer := ByteArray new:8*1024.
   762     buffer := ByteArray new:8*1024.
   614 
   763 
   615     (position isNil "/ i.e. unknown
   764     (position isNil "/ i.e. unknown
   616     or:[newPos < position]) ifTrue:[
   765     or:[newPos < position]) ifTrue:[
   617         self reset.
   766 	self reset.
   618     ].
   767     ].
   619     [position < newPos] whileTrue:[
   768     [position < newPos] whileTrue:[
   620 	amount := (buffer size) min:(newPos-position).
   769 	amount := (buffer size) min:(newPos-position).
   621 	(self nextBytes:amount into:buffer startingAt:1) ~~ amount ifTrue:[
   770 	(self nextBytes:amount into:buffer startingAt:1) ~~ amount ifTrue:[
   622 	    ^ self positionError
   771 	    ^ self positionError
   643      from which a copy can be reconstructed later."
   792      from which a copy can be reconstructed later."
   644 
   793 
   645     aStream nextPutAll:'(FileStream oldFileNamed:'.
   794     aStream nextPutAll:'(FileStream oldFileNamed:'.
   646     aStream nextPutAll:pathName storeString.
   795     aStream nextPutAll:pathName storeString.
   647     (self position ~~ 1) ifTrue:[
   796     (self position ~~ 1) ifTrue:[
   648         aStream nextPutAll:'; position:'.
   797 	aStream nextPutAll:'; position:'.
   649         self position storeOn:aStream
   798 	self position storeOn:aStream
   650     ].
   799     ].
   651     aStream nextPut:$)
   800     aStream nextPut:$)
   652 
   801 
   653     "Modified: 30.7.1997 / 16:43:50 / cg"
   802     "Modified: 30.7.1997 / 16:43:50 / cg"
   654 ! !
   803 ! !
   755     |ok|
   904     |ok|
   756 
   905 
   757     filePointer notNil ifTrue:[^ self errorAlreadyOpen].
   906     filePointer notNil ifTrue:[^ self errorAlreadyOpen].
   758     ok := false.
   907     ok := false.
   759 %{
   908 %{
   760     FILE *f;
   909     HFILE f;
   761     FILE *fopen();
   910     HFILE fopen();
   762     OBJ path, fp;
   911     OBJ path, fp;
   763     int pass = 0;
   912     int pass = 0;
   764 
   913 
   765 retry:
   914 retry:
   766     path = __INST(pathName);
   915     path = __INST(pathName);
   767     if (__isNonNilObject(path) && (__qClass(path)==String)) {
   916     if (__isNonNilObject(path) && (__qClass(path)==String)) {
   768 #ifdef __VMS__
   917 #ifdef __VMS__
   769         do {
   918 	do {
   770             /*
   919 	    /*
   771              * allow passing additional RMS arguments.
   920 	     * allow passing additional RMS arguments.
   772              * stupid: DEC does not seem to offer an interface for passing a char **.
   921 	     * stupid: DEC does not seem to offer an interface for passing a char **.
   773              */
   922 	     */
   774             errno = 0;
   923 	    errno = 0;
   775 
   924 
   776             {
   925 	    {
   777                 if (__isArray(attributeSpec)) {
   926 		if (__isArray(attributeSpec)) {
   778                     OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
   927 		    OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
   779                     int numAttrib = 0;
   928 		    int numAttrib = 0;
   780                     int i;
   929 		    int i;
   781 
   930 
   782                     numAttrib = __arraySize(attributeSpec);
   931 		    numAttrib = __arraySize(attributeSpec);
   783                     for (i=0; i<numAttrib;i++) {
   932 		    for (i=0; i<numAttrib;i++) {
   784                         if (! __isString(ap[i])) {
   933 			if (! __isString(ap[i])) {
   785                             f = NULL;
   934 			    f = NULL;
   786                             errno = EINVAL; /* invalid argument */
   935 			    errno = EINVAL; /* invalid argument */
   787                             goto getOutOfHere;
   936 			    goto getOutOfHere;
   788                         }
   937 			}
   789                     }
   938 		    }
   790                     switch (numAttrib) {
   939 		    switch (numAttrib) {
   791                         case 0:
   940 			case 0:
   792                             __BEGIN_INTERRUPTABLE__
   941 			    __BEGIN_INTERRUPTABLE__
   793                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode));
   942 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode));
   794                             __END_INTERRUPTABLE__
   943 			    __END_INTERRUPTABLE__
   795                             break;
   944 			    break;
   796                         case 1:
   945 			case 1:
   797                             __BEGIN_INTERRUPTABLE__
   946 			    __BEGIN_INTERRUPTABLE__
   798                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   947 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   799                                       __stringVal(ap[0]));
   948 				      __stringVal(ap[0]));
   800                             __END_INTERRUPTABLE__
   949 			    __END_INTERRUPTABLE__
   801                             break;
   950 			    break;
   802                         case 2:
   951 			case 2:
   803                             __BEGIN_INTERRUPTABLE__
   952 			    __BEGIN_INTERRUPTABLE__
   804                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   953 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   805                                       __stringVal(ap[0]), __stringVal(ap[1]));
   954 				      __stringVal(ap[0]), __stringVal(ap[1]));
   806                             __END_INTERRUPTABLE__
   955 			    __END_INTERRUPTABLE__
   807                             break;
   956 			    break;
   808                         case 3:
   957 			case 3:
   809                             __BEGIN_INTERRUPTABLE__
   958 			    __BEGIN_INTERRUPTABLE__
   810                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   959 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   811                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
   960 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]));
   812                             __END_INTERRUPTABLE__
   961 			    __END_INTERRUPTABLE__
   813                             break;
   962 			    break;
   814                         case 4:
   963 			case 4:
   815                             __BEGIN_INTERRUPTABLE__
   964 			    __BEGIN_INTERRUPTABLE__
   816                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   965 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   817                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   966 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   818                                       __stringVal(ap[3]));
   967 				      __stringVal(ap[3]));
   819                             __END_INTERRUPTABLE__
   968 			    __END_INTERRUPTABLE__
   820                             break;
   969 			    break;
   821                         case 5:
   970 			case 5:
   822                             __BEGIN_INTERRUPTABLE__
   971 			    __BEGIN_INTERRUPTABLE__
   823                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   972 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   824                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   973 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   825                                       __stringVal(ap[3]), __stringVal(ap[4]));
   974 				      __stringVal(ap[3]), __stringVal(ap[4]));
   826                             __END_INTERRUPTABLE__
   975 			    __END_INTERRUPTABLE__
   827                             break;
   976 			    break;
   828                         case 6:
   977 			case 6:
   829                             __BEGIN_INTERRUPTABLE__
   978 			    __BEGIN_INTERRUPTABLE__
   830                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   979 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   831                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   980 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   832                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
   981 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]));
   833                             __END_INTERRUPTABLE__
   982 			    __END_INTERRUPTABLE__
   834                             break;
   983 			    break;
   835                         case 7:
   984 			case 7:
   836                             __BEGIN_INTERRUPTABLE__
   985 			    __BEGIN_INTERRUPTABLE__
   837                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   986 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   838                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   987 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   839                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
   988 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
   840                                       __stringVal(ap[6]));
   989 				      __stringVal(ap[6]));
   841                             __END_INTERRUPTABLE__
   990 			    __END_INTERRUPTABLE__
   842                             break;
   991 			    break;
   843                         case 8:
   992 			case 8:
   844                             __BEGIN_INTERRUPTABLE__
   993 			    __BEGIN_INTERRUPTABLE__
   845                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   994 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   846                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   995 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   847                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
   996 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
   848                                       __stringVal(ap[6]), __stringVal(ap[7]));
   997 				      __stringVal(ap[6]), __stringVal(ap[7]));
   849                             __END_INTERRUPTABLE__
   998 			    __END_INTERRUPTABLE__
   850                             break;
   999 			    break;
   851                         case 9:
  1000 			case 9:
   852                             __BEGIN_INTERRUPTABLE__
  1001 			    __BEGIN_INTERRUPTABLE__
   853                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
  1002 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   854                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1003 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   855                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1004 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
   856                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
  1005 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]));
   857                             __END_INTERRUPTABLE__
  1006 			    __END_INTERRUPTABLE__
   858                             break;
  1007 			    break;
   859                         case 10:
  1008 			case 10:
   860                             __BEGIN_INTERRUPTABLE__
  1009 			    __BEGIN_INTERRUPTABLE__
   861                             f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
  1010 			    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode),
   862                                       __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
  1011 				      __stringVal(ap[0]), __stringVal(ap[1]), __stringVal(ap[2]),
   863                                       __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
  1012 				      __stringVal(ap[3]), __stringVal(ap[4]), __stringVal(ap[5]),
   864                                       __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
  1013 				      __stringVal(ap[6]), __stringVal(ap[7]), __stringVal(ap[8]),
   865                                       __stringVal(ap[9]));
  1014 				      __stringVal(ap[9]));
   866                             __END_INTERRUPTABLE__
  1015 			    __END_INTERRUPTABLE__
   867                             break;
  1016 			    break;
   868                         default:
  1017 			default:
   869                             f = NULL;
  1018 			    f = NULL;
   870                             errno = E2BIG; /* too many args */
  1019 			    errno = E2BIG; /* too many args */
   871                             goto getOutOfHere;
  1020 			    goto getOutOfHere;
   872                     }
  1021 		    }
   873                 } else if (attributeSpec != nil) {
  1022 		} else if (attributeSpec != nil) {
   874                     f = NULL;
  1023 		    f = NULL;
   875                     errno = EINVAL; /* invalid argument */
  1024 		    errno = EINVAL; /* invalid argument */
   876                     goto getOutOfHere;
  1025 		    goto getOutOfHere;
   877                 } else {
  1026 		} else {
   878                     /*
  1027 		    /*
   879                      * create file as sequential streamLF by default.
  1028 		     * create file as sequential streamLF by default.
   880                      */
  1029 		     */
   881                     __BEGIN_INTERRUPTABLE__
  1030 		    __BEGIN_INTERRUPTABLE__
   882                     f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode), "rfm=stmlf");
  1031 		    f = fopen((char *)__stringVal(path), (char *)__stringVal(openmode), "rfm=stmlf");
   883                     __END_INTERRUPTABLE__
  1032 		    __END_INTERRUPTABLE__
   884                 }
  1033 		}
   885             }
  1034 	    }
   886             /* must refetch - could be GC'd */
  1035 	    /* must refetch - could be GC'd */
   887             path = __INST(pathName);
  1036 	    path = __INST(pathName);
   888         } while ((f == NULL) && (errno == EINTR));
  1037 	} while ((f == NULL) && (errno == EINTR));
   889 #else
  1038 
   890         do {
  1039 #else /* not VMS */
   891             __BEGIN_INTERRUPTABLE__
  1040 
   892 # ifdef LINUX
  1041 # ifdef WIN32
   893             /* 
  1042 
   894              * LINUX may ret a non-NULL f even when interrupted.
  1043 	do {
   895              * Therefore, check errno and fake a null-ret.
  1044 #  ifdef NO_STDIO
   896              */
  1045 	    /*printf("open %s mode=%s\n",__stringVal(path),__stringVal(openmode)); */
   897             errno = 0;
  1046 #   ifdef DO_WRAP_CALLS
   898             f = fopen((char *) __stringVal(path), (char *) __stringVal(openmode));
  1047 	    f = __STX_C_CALL2((void*)fopen,(void *)__stringVal(path), (void *)__stringVal(openmode));
   899             if (errno == EINTR)
  1048 #   else
   900                 f = NULL;
  1049 	    f = fopen((char *) __stringVal(path), (char *) __stringVal(openmode));
   901 # else
  1050 #   endif
   902             f = fopen((char *) __stringVal(path), (char *) __stringVal(openmode));
  1051 #  else /* use_STDIO */
   903 # endif
  1052 	    __BEGIN_INTERRUPTABLE__
   904             __END_INTERRUPTABLE__
  1053 	    f = fopen((char *) __stringVal(path), (char *) __stringVal(openmode)); 
   905             /* must refetch - could be GC'd */
  1054 	    __END_INTERRUPTABLE__
   906             path = __INST(pathName);
  1055 #  endif /* use_STDIO */
   907         } while ((f == NULL) && (errno == EINTR));
  1056 	    /* must refetch - could be GC'd */
   908 #endif
  1057 	    path = __INST(pathName);
   909 
  1058 	} while ((f == NULL) && (errno == EINTR));
   910         if (f == NULL) {
  1059 
   911             /*
  1060 # else /* not WIN32 */
   912              * If no filedescriptors available, try to finalize
  1061 
   913              * possibly collected fd's and try again.
  1062 	do {
   914              */
  1063 	    __BEGIN_INTERRUPTABLE__
   915             if (pass == 0 && (errno == ENFILE || errno == EMFILE)) {
  1064 #  ifdef LINUX
   916                 pass = 1;
  1065 	    /* 
   917                 __SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
  1066 	     * LINUX may ret a non-NULL f even when interrupted.
   918                 __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
  1067 	     * Therefore, check errno and fake a null-ret.
   919                 goto retry;
  1068 	     */
   920             }
  1069 	    errno = 0;
   921         getOutOfHere: ;
  1070 	    f = fopen((char *) __stringVal(path), (char *) __stringVal(openmode));
   922             __INST(lastErrorNumber) = __MKSMALLINT(errno);
  1071 	    if (errno == EINTR)
   923             __INST(position) = nil;
  1072 		f = NULL;
   924         } else {
  1073 #  else /* not LINUX */
       
  1074 	    f = fopen((char *) __stringVal(path), (char *) __stringVal(openmode));
       
  1075 #  endif /* not LINUX */
       
  1076 	    __END_INTERRUPTABLE__
       
  1077 	    /* must refetch - could be GC'd */
       
  1078 	    path = __INST(pathName);
       
  1079 	} while ((f == NULL) && (errno == EINTR));
       
  1080 
       
  1081 # endif /* not WIN32 */
       
  1082 #endif /* not VMS */
       
  1083 
       
  1084 	if (f == NULL) {
       
  1085 	    /*
       
  1086 	     * If no filedescriptors available, try to finalize
       
  1087 	     * possibly collected fd's and try again.
       
  1088 	     */
       
  1089 	    if (pass == 0 && (errno == ENFILE || errno == EMFILE)) {
       
  1090 		pass = 1;
       
  1091 		__SSEND0(@global(ObjectMemory), @symbol(scavenge), 0);
       
  1092 		__SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
       
  1093 		goto retry;
       
  1094 	    }
       
  1095 	getOutOfHere: ;
       
  1096 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
       
  1097 	    __INST(position) = nil;
       
  1098 	} else {
   925 #ifdef __VMS__
  1099 #ifdef __VMS__
   926             /*
  1100 	    /*
   927              * check to see if this is positionable ...
  1101 	     * check to see if this is positionable ...
   928              */
  1102 	     */
   929             __INST(canPosition) = false;
  1103 	    __INST(canPosition) = false;
   930 # ifndef _POSIX_C_SOURCE
  1104 # ifndef _POSIX_C_SOURCE
   931             {
  1105 	    {
   932                 struct stat statBuffer;
  1106 		struct stat statBuffer;
   933 
  1107 
   934                 if (fstat(fileno(f), &statBuffer) >= 0) {
  1108 		if (fstat(fileno(f), &statBuffer) >= 0) {
   935                     switch (statBuffer.st_fab_rfm) {
  1109 		    switch (statBuffer.st_fab_rfm) {
   936                         case FAB$C_UDF: /* undefined (also stream binary)   */
  1110 			case FAB$C_UDF: /* undefined (also stream binary)   */
   937                         case FAB$C_VAR: /* variable length records          */
  1111 			case FAB$C_VAR: /* variable length records          */
   938                         case FAB$C_VFC: /* variable fixed control           */
  1112 			case FAB$C_VFC: /* variable fixed control           */
   939                         case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */
  1113 			case FAB$C_STM: /* RMS-11 stream (valid only for sequen> */
   940                         default:
  1114 			default:
   941                             __INST(canPosition) = false;
  1115 			    __INST(canPosition) = false;
   942                             break;
  1116 			    break;
   943 
  1117 
   944                         case FAB$C_FIX: /* fixed length records             */
  1118 			case FAB$C_FIX: /* fixed length records             */
   945                         case FAB$C_STMLF: /* LF stream (valid only for sequential> */
  1119 			case FAB$C_STMLF: /* LF stream (valid only for sequential> */
   946                         case FAB$C_STMCR: /* CR stream (valid only for sequential> */
  1120 			case FAB$C_STMCR: /* CR stream (valid only for sequential> */
   947                             __INST(canPosition) = true;
  1121 			    __INST(canPosition) = true;
   948                             break;
  1122 			    break;
   949                     }
  1123 		    }
   950                 }
  1124 		}
   951             }
  1125 	    }
   952 # endif 
  1126 # endif 
   953 #else /* not VMS */
  1127 #else /* not VMS */
   954             __INST(canPosition) = true;
  1128 	    __INST(canPosition) = true;
   955 #endif /* poor VMS */
  1129 #endif /* poor VMS */
   956 
  1130 
   957             __INST(filePointer) = fp = __MKOBJ((INT)f); __STORE(self, fp);
  1131 	    __INST(filePointer) = fp = __MKOBJ((INT)f); __STORE(self, fp);
   958             __INST(position) = __MKSMALLINT(1);
  1132 	    __INST(position) = __MKSMALLINT(1);
   959             ok = true;
  1133 	    ok = true;
   960         }
  1134 	}
   961     }
  1135     }
   962 %}.
  1136 %}.
   963     ok ifFalse:[
  1137     ok ifFalse:[
   964         "
  1138 	"
   965          the open failed for some reason ...
  1139 	 the open failed for some reason ...
   966         "
  1140 	"
   967         ^ self openError
  1141 	^ self openError
   968     ].
  1142     ].
   969     buffered := true.       "default is buffered"
  1143     buffered := true.       "default is buffered"
   970     Lobby register:self.
  1144     Lobby register:self.
   971 !
  1145 !
   972 
  1146 
  1002 	    "/ the file is no longer present or accessable ..."
  1176 	    "/ the file is no longer present or accessable ..."
  1003 
  1177 
  1004 	    (self class name , ' [warning]: could not reOpen file: ', pathName) errorPrintCR.
  1178 	    (self class name , ' [warning]: could not reOpen file: ', pathName) errorPrintCR.
  1005 	] ifFalse:[
  1179 	] ifFalse:[
  1006 	    oldPos notNil ifTrue:[
  1180 	    oldPos notNil ifTrue:[
  1007 	        self position:oldPos.
  1181 		self position:oldPos.
  1008 	    ]
  1182 	    ]
  1009 	]
  1183 	]
  1010     ]
  1184     ]
  1011 
  1185 
  1012     "Modified: 10.1.1997 / 17:50:51 / cg"
  1186     "Modified: 10.1.1997 / 17:50:51 / cg"
  1021 fileSize
  1195 fileSize
  1022     "return the size in bytes of the file"
  1196     "return the size in bytes of the file"
  1023 
  1197 
  1024 %{
  1198 %{
  1025 
  1199 
       
  1200     HFILE f;
       
  1201 
  1026 #ifdef transputer
  1202 #ifdef transputer
  1027     FILE *f;
       
  1028     int size;
  1203     int size;
  1029 
  1204 
  1030     if (__INST(filePointer) != nil) {
  1205     if (__INST(filePointer) != nil) {
  1031 	f = __FILEVal(__INST(filePointer));
  1206 	f = __FILEVal(__INST(filePointer));
  1032 	if ((size = filesize(fileno(f))) >= 0) {
  1207 	if ((size = filesize(fileno(f))) >= 0) {
  1033 	    RETURN ( __MKSMALLINT(size) );
  1208 	    RETURN ( __MKSMALLINT(size) );
  1034 	}
  1209 	}
  1035     }
  1210     }
  1036 #else
  1211 #else
  1037     FILE *f;
       
  1038     struct stat buf;
  1212     struct stat buf;
  1039     int ret;
  1213     int ret;
  1040     int fd;
  1214     int fd;
  1041 
  1215 
  1042     if (__INST(filePointer) != nil) {
  1216     if (__INST(filePointer) != nil) {
  1088 ! !
  1262 ! !
  1089 
  1263 
  1090 !FileStream class methodsFor:'documentation'!
  1264 !FileStream class methodsFor:'documentation'!
  1091 
  1265 
  1092 version
  1266 version
  1093     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.67 1999-10-13 12:25:40 cg Exp $'
  1267     ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.68 1999-10-14 23:51:01 cg Exp $'
  1094 ! !
  1268 ! !
  1095 FileStream initialize!
  1269 FileStream initialize!