ExternalStream.st
changeset 16296 f8548919e174
parent 15994 cbd013980da3
child 16300 277c0cb1ecbc
equal deleted inserted replaced
16295:54510929f67c 16296:f8548919e174
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
       
    12 
    12 "{ Package: 'stx:libbasic' }"
    13 "{ Package: 'stx:libbasic' }"
    13 
    14 
    14 ReadWriteStream subclass:#ExternalStream
    15 ReadWriteStream subclass:#ExternalStream
    15 	instanceVariableNames:'handleType handle mode buffered binary eolMode hitEOF didWrite
    16 	instanceVariableNames:'handleType handle mode buffered binary eolMode hitEOF didWrite
    16 		lastErrorNumber readAhead'
    17 		lastErrorNumber readAhead'
    23 	category:'Streams-External'
    24 	category:'Streams-External'
    24 !
    25 !
    25 
    26 
    26 !ExternalStream primitiveDefinitions!
    27 !ExternalStream primitiveDefinitions!
    27 %{
    28 %{
    28 
       
    29 #undef fwrite
    29 #undef fwrite
    30 
    30 
    31 #include <stdio.h>
    31 #include <stdio.h>
    32 #define _STDIO_H_INCLUDED_
    32 #define _STDIO_H_INCLUDED_
    33 
       
    34 
    33 
    35 #ifndef NO_FCNTL_H
    34 #ifndef NO_FCNTL_H
    36 # include <fcntl.h>
    35 # include <fcntl.h>
    37 # define _FCNTL_H_INCLUDED_
    36 # define _FCNTL_H_INCLUDED_
    38 #endif
    37 #endif
   197 #ifdef DEBUGGING
   196 #ifdef DEBUGGING
   198   extern char *__survStartPtr, *__survEndPtr;
   197   extern char *__survStartPtr, *__survEndPtr;
   199 # define DEBUGBUFFER(buf)  \
   198 # define DEBUGBUFFER(buf)  \
   200     if (((char *)(buf) >= __survStartPtr) \
   199     if (((char *)(buf) >= __survStartPtr) \
   201      && ((char *)(buf) < __survEndPtr)) { \
   200      && ((char *)(buf) < __survEndPtr)) { \
   202         __fatal0("read into survivor\n"); \
   201 	__fatal0("read into survivor\n"); \
   203     }
   202     }
   204 
   203 
   205 #else
   204 #else
   206 # define DEBUGBUFFER(buf) /* nothing */
   205 # define DEBUGBUFFER(buf) /* nothing */
   207 #endif
   206 #endif
   217 #else
   216 #else
   218 # define OPT_FSEEK(f, pos, whence)      /* nothing */
   217 # define OPT_FSEEK(f, pos, whence)      /* nothing */
   219 #endif
   218 #endif
   220 
   219 
   221 #ifdef WIN32
   220 #ifdef WIN32
   222 
       
   223 # ifdef __BORLANDC__
   221 # ifdef __BORLANDC__
   224    int _rtl_read();
   222    int _rtl_read();
   225    int _rtl_write();
   223    int _rtl_write();
   226 
   224 
   227 #  define READ(ret,f, cp, n, handleType) \
   225 #  define READ(ret,f, cp, n, handleType) \
   228       { int __res;\
   226       { int __res;\
   229         HANDLE h; \
   227 	HANDLE h; \
   230         h = _get_osfhandle(fileno(f)); \
   228 	h = _get_osfhandle(fileno(f)); \
   231         if ((handleType == @symbol(socketFilePointer)) \
   229 	if ((handleType == @symbol(socketFilePointer)) \
   232         || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   230 	|| ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   233           (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
   231 	  (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
   234         } else { \
   232 	} else { \
   235           (ret) = __STX_C_NOINT_CALL3("_rtl_read", _rtl_read, fileno(f), (cp), (n));\
   233 	  (ret) = __STX_C_NOINT_CALL3("_rtl_read", _rtl_read, fileno(f), (cp), (n));\
   236         } \
   234 	} \
   237       }
   235       }
   238 
   236 
   239 #  define WRITE(ret,f, cp, n, handleType) \
   237 #  define WRITE(ret,f, cp, n, handleType) \
   240       { int __res;\
   238       { int __res;\
   241         HANDLE h; \
   239 	HANDLE h; \
   242         h = _get_osfhandle(fileno(f)); \
   240 	h = _get_osfhandle(fileno(f)); \
   243         if ((handleType == @symbol(socketFilePointer)) \
   241 	if ((handleType == @symbol(socketFilePointer)) \
   244         || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   242 	|| ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   245           (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
   243 	  (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
   246         } else { \
   244 	} else { \
   247           (ret) = __STX_C_NOINT_CALL3("_rtl_write", _rtl_write, fileno(f), (cp), (n));\
   245 	  (ret) = __STX_C_NOINT_CALL3("_rtl_write", _rtl_write, fileno(f), (cp), (n));\
   248         } \
   246 	} \
   249       }
   247       }
   250 
   248 
   251 # else /* MSC */
   249 # else /* MSC */
   252 
   250 
   253 #  define READ(ret,f, cp, n, handleType) \
   251 #  define READ(ret,f, cp, n, handleType) \
   254       { int __res;\
   252       { int __res;\
   255         int fd; \
   253 	int fd; \
   256         HANDLE h; \
   254 	HANDLE h; \
   257         fd = fileno(f); \
   255 	fd = fileno(f); \
   258         if ((handleType == @symbol(socketFileDescriptor)) \
   256 	if ((handleType == @symbol(socketFileDescriptor)) \
   259          || ((handleType == nil) && (ioctlsocket((SOCKET)fd,FIONREAD,&__res)==0))) { \
   257 	 || ((handleType == nil) && (ioctlsocket((SOCKET)fd,FIONREAD,&__res)==0))) { \
   260           (ret) = __STX_WSA_NOINT_CALL4("recv", recv, fd, (cp), (n), 0);\
   258 	  (ret) = __STX_WSA_NOINT_CALL4("recv", recv, fd, (cp), (n), 0);\
   261         } else { \
   259 	} else { \
   262           h = _get_osfhandle(fd); \
   260 	  h = _get_osfhandle(fd); \
   263           if ((handleType == @symbol(socketFilePointer)) \
   261 	  if ((handleType == @symbol(socketFilePointer)) \
   264           || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   262 	  || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   265             (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
   263 	    (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
   266           } else { \
   264 	  } else { \
   267             (ret) = __STX_API_NOINT_CALL5("ReadFile", ReadFile, h, (cp), (n), &__res, 0);\
   265 	    (ret) = __STX_API_NOINT_CALL5("ReadFile", ReadFile, h, (cp), (n), &__res, 0);\
   268             if (ret) \
   266 	    if (ret) \
   269               ret = __res; \
   267 	      ret = __res; \
   270           } \
   268 	  } \
   271         } \
   269 	} \
   272       }
   270       }
   273 #  define WRITE(ret,f, cp, n, handleType) \
   271 #  define WRITE(ret,f, cp, n, handleType) \
   274       { int __res;\
   272       { int __res;\
   275         int fd; \
   273 	int fd; \
   276         HANDLE h; \
   274 	HANDLE h; \
   277         fd = fileno(f); \
   275 	fd = fileno(f); \
   278         if ((handleType == @symbol(socketFileDescriptor)) \
   276 	if ((handleType == @symbol(socketFileDescriptor)) \
   279          || ((handleType == nil) && (ioctlsocket((SOCKET)fd,FIONREAD,&__res)==0))) { \
   277 	 || ((handleType == nil) && (ioctlsocket((SOCKET)fd,FIONREAD,&__res)==0))) { \
   280           (ret) = __STX_WSA_NOINT_CALL4("send", send, fd, (cp), (n), 0);\
   278 	  (ret) = __STX_WSA_NOINT_CALL4("send", send, fd, (cp), (n), 0);\
   281         } else {\
   279 	} else {\
   282           h = _get_osfhandle(fd); \
   280 	  h = _get_osfhandle(fd); \
   283           if ((handleType == @symbol(socketFilePointer)) \
   281 	  if ((handleType == @symbol(socketFilePointer)) \
   284           || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   282 	  || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
   285             (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
   283 	    (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
   286           } else {\
   284 	  } else {\
   287             (ret) = __STX_API_NOINT_CALL5("WriteFile", WriteFile, h, (cp), (n), &__res, 0);\
   285 	    (ret) = __STX_API_NOINT_CALL5("WriteFile", WriteFile, h, (cp), (n), &__res, 0);\
   288             if (ret) \
   286 	    if (ret) \
   289               ret = __res; \
   287 	      ret = __res; \
   290           } \
   288 	  } \
   291         } \
   289 	} \
   292       }
   290       }
   293 # endif /* MSC */
   291 # endif /* MSC */
   294 
   292 
   295 # define FFLUSH(fp)             fflush(fp)
   293 # define FFLUSH(fp)             fflush(fp)
   296 # undef STDIO_NEEDS_FSEEK
   294 # undef STDIO_NEEDS_FSEEK
   298 # define FILENO(f)              fileno(f)
   296 # define FILENO(f)              fileno(f)
   299 
   297 
   300 # define __READING__(f)                          \
   298 # define __READING__(f)                          \
   301     if ((__INST(didWrite) != false)              \
   299     if ((__INST(didWrite) != false)              \
   302      && (__INST(mode) == @symbol(readwrite))) {  \
   300      && (__INST(mode) == @symbol(readwrite))) {  \
   303         __INST(didWrite) = false;                \
   301 	__INST(didWrite) = false;                \
   304         OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   302 	OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   305     }
   303     }
   306 
   304 
   307 # define __WRITING__(f)                          \
   305 # define __WRITING__(f)                          \
   308     if ((__INST(didWrite) != true)               \
   306     if ((__INST(didWrite) != true)               \
   309      && (__INST(mode) == @symbol(readwrite))) {  \
   307      && (__INST(mode) == @symbol(readwrite))) {  \
   310         __INST(didWrite) = true;                 \
   308 	__INST(didWrite) = true;                 \
   311         OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   309 	OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   312     }
   310     }
   313 
   311 
   314 # define __UNGETC__(c, f, isBuffered)                   \
   312 # define __UNGETC__(c, f, isBuffered)                   \
   315     if (isBuffered) {                                   \
   313     if (isBuffered) {                                   \
   316         ungetc((c), (f));                               \
   314 	ungetc((c), (f));                               \
   317     } else {                                            \
   315     } else {                                            \
   318       __INST(readAhead) = __mkSmallInteger((c));            \
   316       __INST(readAhead) = __mkSmallInteger((c));            \
   319     }
   317     }
   320 
   318 
   321 # define __READBYTE__(ret, f, buf, isBuffered, handleType)          \
   319 # define __READBYTE__(ret, f, buf, isBuffered, handleType)          \
   322     if (isBuffered) {                                   \
   320     if (isBuffered) {                                   \
   323         for (;;) {                                      \
   321 	for (;;) {                                      \
   324             CLEAR_ERRNO;                                \
   322 	    CLEAR_ERRNO;                                \
   325             (ret) = getc(f);                            \
   323 	    (ret) = getc(f);                            \
   326             if ((ret) >= 0) {                           \
   324 	    if ((ret) >= 0) {                           \
   327                 *(buf) = (ret);                         \
   325 		*(buf) = (ret);                         \
   328                 (ret) = 1;                              \
   326 		(ret) = 1;                              \
   329             } else if (ferror(f)) {                     \
   327 	    } else if (ferror(f)) {                     \
   330                 if (__threadErrno == EINTR) {           \
   328 		if (__threadErrno == EINTR) {           \
   331                     clearerr(f);                        \
   329 		    clearerr(f);                        \
   332                     continue;                           \
   330 		    continue;                           \
   333                 }                                       \
   331 		}                                       \
   334             } else {                                    \
   332 	    } else {                                    \
   335                 (ret) = 0;                              \
   333 		(ret) = 0;                              \
   336             }                                           \
   334 	    }                                           \
   337             break;                                      \
   335 	    break;                                      \
   338         }                                               \
   336 	}                                               \
   339     } else {                                            \
   337     } else {                                            \
   340         OBJ rA = __INST(readAhead);                     \
   338 	OBJ rA = __INST(readAhead);                     \
   341         if (rA != nil) {                                \
   339 	if (rA != nil) {                                \
   342             *(buf) = (char)__intVal(rA);                \
   340 	    *(buf) = (char)__intVal(rA);                \
   343             __INST(readAhead) = nil;                    \
   341 	    __INST(readAhead) = nil;                    \
   344             (ret) = 1;                                  \
   342 	    (ret) = 1;                                  \
   345         } else {                                        \
   343 	} else {                                        \
   346             for (;;) {                                  \
   344 	    for (;;) {                                  \
   347                 CLEAR_ERRNO;                            \
   345 		CLEAR_ERRNO;                            \
   348                 READ(ret,f, buf, 1, handleType);                    \
   346 		READ(ret,f, buf, 1, handleType);                    \
   349                 if ((ret) >= 0 || __threadErrno != EINTR)       \
   347 		if ((ret) >= 0 || __threadErrno != EINTR)       \
   350                     break;                              \
   348 		    break;                              \
   351             }                                           \
   349 	    }                                           \
   352         }                                               \
   350 	}                                               \
   353     }
   351     }
   354 
   352 
   355   /*
   353   /*
   356    * read_bytes into a c-buffer
   354    * read_bytes into a c-buffer
   357    * (which may NOT move)
   355    * (which may NOT move)
   358    */
   356    */
   359 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType)    \
   357 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType)    \
   360     (ret) = 0;                                          \
   358     (ret) = 0;                                          \
   361     if (isBuffered) {                                   \
   359     if (isBuffered) {                                   \
   362         int __offs = 0;                                 \
   360 	int __offs = 0;                                 \
   363         while (__offs < (cnt)) {                        \
   361 	while (__offs < (cnt)) {                        \
   364             CLEAR_ERRNO;                                \
   362 	    CLEAR_ERRNO;                                \
   365             (ret) = getc(f);                            \
   363 	    (ret) = getc(f);                            \
   366             if ((ret) < 0) {                            \
   364 	    if ((ret) < 0) {                            \
   367                 if (ferror(f)) {                        \
   365 		if (ferror(f)) {                        \
   368                     if (__threadErrno == EINTR) {               \
   366 		    if (__threadErrno == EINTR) {               \
   369                         clearerr(f);                    \
   367 			clearerr(f);                    \
   370                         continue;                       \
   368 			continue;                       \
   371                     }                                   \
   369 		    }                                   \
   372                 } else {                                \
   370 		} else {                                \
   373                     (ret) = 0;                          \
   371 		    (ret) = 0;                          \
   374                 }                                       \
   372 		}                                       \
   375                 break;                                  \
   373 		break;                                  \
   376             }                                           \
   374 	    }                                           \
   377             (buf)[__offs++] = (ret);                    \
   375 	    (buf)[__offs++] = (ret);                    \
   378         }                                               \
   376 	}                                               \
   379         if (__offs > 0)                                 \
   377 	if (__offs > 0)                                 \
   380             (ret) = __offs;                             \
   378 	    (ret) = __offs;                             \
   381     } else {                                            \
   379     } else {                                            \
   382         int __offs = 0;                                 \
   380 	int __offs = 0;                                 \
   383                                                         \
   381 							\
   384         while (__offs < (cnt)) {                        \
   382 	while (__offs < (cnt)) {                        \
   385             OBJ rA = __INST(readAhead);                 \
   383 	    OBJ rA = __INST(readAhead);                 \
   386             if (rA != nil) {                            \
   384 	    if (rA != nil) {                            \
   387                 (buf)[__offs] = __intVal(rA);           \
   385 		(buf)[__offs] = __intVal(rA);           \
   388                 __INST(readAhead) = nil;                \
   386 		__INST(readAhead) = nil;                \
   389                 (ret) = 1;                              \
   387 		(ret) = 1;                              \
   390             } else {                                    \
   388 	    } else {                                    \
   391                 CLEAR_ERRNO;                            \
   389 		CLEAR_ERRNO;                            \
   392                 READ(ret,f, (buf)+__offs, (cnt)-__offs, handleType); \
   390 		READ(ret,f, (buf)+__offs, (cnt)-__offs, handleType); \
   393                 if ((ret) <= 0) {                       \
   391 		if ((ret) <= 0) {                       \
   394                     if ((ret) < 0 && __threadErrno == EINTR) {  \
   392 		    if ((ret) < 0 && __threadErrno == EINTR) {  \
   395                         continue;                       \
   393 			continue;                       \
   396                     }                                   \
   394 		    }                                   \
   397                     break;                              \
   395 		    break;                              \
   398                 }                                       \
   396 		}                                       \
   399             }                                           \
   397 	    }                                           \
   400             __offs += (ret);                            \
   398 	    __offs += (ret);                            \
   401         }                                               \
   399 	}                                               \
   402         if (__offs > 0)                                 \
   400 	if (__offs > 0)                                 \
   403             (ret) = __offs;                             \
   401 	    (ret) = __offs;                             \
   404    }
   402    }
   405 
   403 
   406 # define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \
   404 # define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \
   407   {                                                     \
   405   {                                                     \
   408     int __offs = 0;                                     \
   406     int __offs = 0;                                     \
   409     int oldFlags;                                       \
   407     int oldFlags;                                       \
   410                                                         \
   408 							\
   411     (ret) = 0;                                          \
   409     (ret) = 0;                                          \
   412     if (isBuffered) {                                   \
   410     if (isBuffered) {                                   \
   413         while (__offs < (cnt)) {                        \
   411 	while (__offs < (cnt)) {                        \
   414             CLEAR_ERRNO;                                \
   412 	    CLEAR_ERRNO;                                \
   415             (ret) = getc(f);                            \
   413 	    (ret) = getc(f);                            \
   416             if ((ret) < 0) {                            \
   414 	    if ((ret) < 0) {                            \
   417                 if (ferror(f)) {                        \
   415 		if (ferror(f)) {                        \
   418                     if (__threadErrno == EINTR) {               \
   416 		    if (__threadErrno == EINTR) {               \
   419                         clearerr(f);                    \
   417 			clearerr(f);                    \
   420                         continue;                       \
   418 			continue;                       \
   421                     }                                   \
   419 		    }                                   \
   422                 } else {                                \
   420 		} else {                                \
   423                     (ret) = 0;                          \
   421 		    (ret) = 0;                          \
   424                 }                                       \
   422 		}                                       \
   425                 break;                                  \
   423 		break;                                  \
   426             }                                           \
   424 	    }                                           \
   427             (buf)[__offs++] = (ret);                    \
   425 	    (buf)[__offs++] = (ret);                    \
   428         }                                               \
   426 	}                                               \
   429         if (__offs > 0)                                 \
   427 	if (__offs > 0)                                 \
   430             (ret) = __offs;                             \
   428 	    (ret) = __offs;                             \
   431     } else {                                            \
   429     } else {                                            \
   432         while (__offs < (cnt)) {                        \
   430 	while (__offs < (cnt)) {                        \
   433             OBJ rA = __INST(readAhead);                 \
   431 	    OBJ rA = __INST(readAhead);                 \
   434             if (rA != nil) {                            \
   432 	    if (rA != nil) {                            \
   435                 (buf)[__offs] = __intVal(rA);           \
   433 		(buf)[__offs] = __intVal(rA);           \
   436                 __INST(readAhead) = nil;                \
   434 		__INST(readAhead) = nil;                \
   437                 (ret) = 1;                              \
   435 		(ret) = 1;                              \
   438                 __offs += (ret);                        \
   436 		__offs += (ret);                        \
   439                 continue;                               \
   437 		continue;                               \
   440             }                                           \
   438 	    }                                           \
   441             CLEAR_ERRNO;                                \
   439 	    CLEAR_ERRNO;                                \
   442             {                                           \
   440 	    {                                           \
   443               int res;                                  \
   441 	      int res;                                  \
   444               if ((handleType == @symbol(socketFilePointer)) \
   442 	      if ((handleType == @symbol(socketFilePointer)) \
   445                || ((handleType == nil) && (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res)==0))) { \
   443 	       || ((handleType == nil) && (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res)==0))) { \
   446                   if (res > 0) {                        \
   444 		  if (res > 0) {                        \
   447                       if (res > ((cnt)-__offs))         \
   445 		      if (res > ((cnt)-__offs))         \
   448                         res = (cnt)-__offs;             \
   446 			res = (cnt)-__offs;             \
   449                       READ(ret,f, (buf)+__offs, res, handleType);   \
   447 		      READ(ret,f, (buf)+__offs, res, handleType);   \
   450                   } else {                              \
   448 		  } else {                              \
   451                       (ret) = 0;                        \
   449 		      (ret) = 0;                        \
   452                   }                                     \
   450 		  }                                     \
   453               } else if ((handleType == @symbol(pipeFilePointer)) \
   451 	      } else if ((handleType == @symbol(pipeFilePointer)) \
   454                          || ((handleType == nil) && (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)))) { \
   452 			 || ((handleType == nil) && (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)))) { \
   455                   if (res > 0) {                        \
   453 		  if (res > 0) {                        \
   456                       if (res > ((cnt)-__offs))         \
   454 		      if (res > ((cnt)-__offs))         \
   457                         res = (cnt)-__offs;             \
   455 			res = (cnt)-__offs;             \
   458                       READ(ret,f, (buf)+__offs, res, handleType);   \
   456 		      READ(ret,f, (buf)+__offs, res, handleType);   \
   459                   } else                                \
   457 		  } else                                \
   460                       ret = 0;                          \
   458 		      ret = 0;                          \
   461               } else {                                  \
   459 	      } else {                                  \
   462                   READ(ret,f, (buf)+__offs, (cnt)-__offs, handleType); \
   460 		  READ(ret,f, (buf)+__offs, (cnt)-__offs, handleType); \
   463               }                                         \
   461 	      }                                         \
   464             }                                           \
   462 	    }                                           \
   465             if ((ret) < 0) {                            \
   463 	    if ((ret) < 0) {                            \
   466                 if (__threadErrno == EINTR) {                   \
   464 		if (__threadErrno == EINTR) {                   \
   467                     continue;                           \
   465 		    continue;                           \
   468                 }                                       \
   466 		}                                       \
   469                 break;                                  \
   467 		break;                                  \
   470             }                                           \
   468 	    }                                           \
   471             __offs += (ret);                            \
   469 	    __offs += (ret);                            \
   472             break;                                      \
   470 	    break;                                      \
   473         }                                               \
   471 	}                                               \
   474         if (__offs > 0)                                 \
   472 	if (__offs > 0)                                 \
   475             (ret) = __offs;                             \
   473 	    (ret) = __offs;                             \
   476     }                                                   \
   474     }                                                   \
   477   }
   475   }
   478 
   476 
   479 # define IO_BUFFER_SIZE        (8*1024)
   477 # define IO_BUFFER_SIZE        (8*1024)
   480 
   478 
   481 # define __READBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \
   479 # define __READBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \
   482   {                                                     \
   480   {                                                     \
   483     int __ooffs = obj_offs;                             \
   481     int __ooffs = obj_offs;                             \
   484     int __offs = 0;                                     \
   482     int __offs = 0;                                     \
   485     char *buf = (char *)(obj);                          \
   483     char *buf = (char *)(obj);                          \
   486                                                         \
   484 							\
   487     (ret) = 0;                                          \
   485     (ret) = 0;                                          \
   488     if (isBuffered) {                                   \
   486     if (isBuffered) {                                   \
   489         while (__offs < (cnt)) {                        \
   487 	while (__offs < (cnt)) {                        \
   490             CLEAR_ERRNO;                                \
   488 	    CLEAR_ERRNO;                                \
   491             (ret) = getc(f);                            \
   489 	    (ret) = getc(f);                            \
   492             if ((ret) < 0) {                            \
   490 	    if ((ret) < 0) {                            \
   493                 if (ferror(f)) {                        \
   491 		if (ferror(f)) {                        \
   494                     if (__threadErrno == EINTR) {       \
   492 		    if (__threadErrno == EINTR) {       \
   495                         clearerr(f);                    \
   493 			clearerr(f);                    \
   496                         /* refetch */                   \
   494 			/* refetch */                   \
   497                         buf = (char *)(obj);   \
   495 			buf = (char *)(obj);   \
   498                         continue;                       \
   496 			continue;                       \
   499                     }                                   \
   497 		    }                                   \
   500                 } else {                                \
   498 		} else {                                \
   501                     (ret) = 0;                          \
   499 		    (ret) = 0;                          \
   502                 }                                       \
   500 		}                                       \
   503                 break;                                  \
   501 		break;                                  \
   504             }                                           \
   502 	    }                                           \
   505             (buf)[__ooffs+__offs] = (ret);              \
   503 	    (buf)[__ooffs+__offs] = (ret);              \
   506             __offs++;                                   \
   504 	    __offs++;                                   \
   507         }                                               \
   505 	}                                               \
   508         if (__offs > 0)                                 \
   506 	if (__offs > 0)                                 \
   509             (ret) = __offs;                             \
   507 	    (ret) = __offs;                             \
   510     } else {                                            \
   508     } else {                                            \
   511         while (__offs < (cnt)) {                        \
   509 	while (__offs < (cnt)) {                        \
   512             char __buf[IO_BUFFER_SIZE];                 \
   510 	    char __buf[IO_BUFFER_SIZE];                 \
   513             OBJ rA = __INST(readAhead);                 \
   511 	    OBJ rA = __INST(readAhead);                 \
   514             if (rA != nil) {                            \
   512 	    if (rA != nil) {                            \
   515                 (buf)[__ooffs+__offs] = __intVal(rA);   \
   513 		(buf)[__ooffs+__offs] = __intVal(rA);   \
   516                 __INST(readAhead) = nil;                \
   514 		__INST(readAhead) = nil;                \
   517                 (ret) = 1;                              \
   515 		(ret) = 1;                              \
   518             } else {                                    \
   516 	    } else {                                    \
   519                 int l;                                  \
   517 		int l;                                  \
   520                 CLEAR_ERRNO;                            \
   518 		CLEAR_ERRNO;                            \
   521                 l = (cnt)-__offs;                       \
   519 		l = (cnt)-__offs;                       \
   522                 if ( l > IO_BUFFER_SIZE)                \
   520 		if ( l > IO_BUFFER_SIZE)                \
   523                   l = IO_BUFFER_SIZE;                   \
   521 		  l = IO_BUFFER_SIZE;                   \
   524                 READ(ret,f, __buf, l, handleType);                  \
   522 		READ(ret,f, __buf, l, handleType);                  \
   525                 if ((ret) <= 0) {                       \
   523 		if ((ret) <= 0) {                       \
   526                     if ((ret) < 0 && __threadErrno == EINTR) {  \
   524 		    if ((ret) < 0 && __threadErrno == EINTR) {  \
   527                         continue;                       \
   525 			continue;                       \
   528                     }                                   \
   526 		    }                                   \
   529                     break;                              \
   527 		    break;                              \
   530                 }                                       \
   528 		}                                       \
   531             }                                           \
   529 	    }                                           \
   532             if( (ret) > 0 ) {                               \
   530 	    if( (ret) > 0 ) {                               \
   533                 /* refetch */                               \
   531 		/* refetch */                               \
   534                 buf = (char *)(obj);               \
   532 		buf = (char *)(obj);               \
   535                 memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   533 		memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   536                 __offs += (ret);                            \
   534 		__offs += (ret);                            \
   537             } else {                                        \
   535 	    } else {                                        \
   538                 (ret) = 0;                                  \
   536 		(ret) = 0;                                  \
   539             }                                               \
   537 	    }                                               \
   540         }                                               \
   538 	}                                               \
   541         if (__offs > 0)                                 \
   539 	if (__offs > 0)                                 \
   542             (ret) = __offs;                             \
   540 	    (ret) = __offs;                             \
   543     }                                                   \
   541     }                                                   \
   544   }
   542   }
   545 
   543 
   546 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)\
   544 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)\
   547   {                                                  \
   545   {                                                  \
   548     int __ooffs = obj_offs;                          \
   546     int __ooffs = obj_offs;                          \
   549     int __offs = 0;                                  \
   547     int __offs = 0;                                  \
   550     char *buf = (char *)(obj);                       \
   548     char *buf = (char *)(obj);                       \
   551                                                      \
   549 						     \
   552     (ret) = 0;                                       \
   550     (ret) = 0;                                       \
   553     if (isBuffered) {                                \
   551     if (isBuffered) {                                \
   554         while (__offs < (cnt)) {                     \
   552 	while (__offs < (cnt)) {                     \
   555             CLEAR_ERRNO;                             \
   553 	    CLEAR_ERRNO;                             \
   556             (ret) = getc(f);                         \
   554 	    (ret) = getc(f);                         \
   557             if ((ret) < 0) {                         \
   555 	    if ((ret) < 0) {                         \
   558                 if (ferror(f)) {                     \
   556 		if (ferror(f)) {                     \
   559                     if (__threadErrno == EINTR) {    \
   557 		    if (__threadErrno == EINTR) {    \
   560                         clearerr(f);                 \
   558 			clearerr(f);                 \
   561                         /* refetch */                \
   559 			/* refetch */                \
   562                         buf = (char *)(obj);\
   560 			buf = (char *)(obj);\
   563                         continue;                    \
   561 			continue;                    \
   564                     }                                \
   562 		    }                                \
   565                 } else {                             \
   563 		} else {                             \
   566                     (ret) = 0;                       \
   564 		    (ret) = 0;                       \
   567                 }                                    \
   565 		}                                    \
   568                 break;                               \
   566 		break;                               \
   569             }                                        \
   567 	    }                                        \
   570             (buf)[__ooffs+__offs] = (ret);           \
   568 	    (buf)[__ooffs+__offs] = (ret);           \
   571             __offs++;                                \
   569 	    __offs++;                                \
   572         }                                            \
   570 	}                                            \
   573         if (__offs > 0)                              \
   571 	if (__offs > 0)                              \
   574             (ret) = __offs;                          \
   572 	    (ret) = __offs;                          \
   575     } else {                                         \
   573     } else {                                         \
   576         while (__offs < (cnt)) {                     \
   574 	while (__offs < (cnt)) {                     \
   577             char __buf[IO_BUFFER_SIZE];              \
   575 	    char __buf[IO_BUFFER_SIZE];              \
   578             OBJ rA = __INST(readAhead);              \
   576 	    OBJ rA = __INST(readAhead);              \
   579             if (rA != nil) {                         \
   577 	    if (rA != nil) {                         \
   580                 (buf)[__ooffs+__offs] = __intVal(rA);\
   578 		(buf)[__ooffs+__offs] = __intVal(rA);\
   581                 __INST(readAhead) = nil;             \
   579 		__INST(readAhead) = nil;             \
   582                 (ret) = 1;                           \
   580 		(ret) = 1;                           \
   583                 __offs += (ret);                     \
   581 		__offs += (ret);                     \
   584                 continue;                            \
   582 		continue;                            \
   585             }                                        \
   583 	    }                                        \
   586             {                                        \
   584 	    {                                        \
   587                 int l;                               \
   585 		int l;                               \
   588                 int res;                             \
   586 		int res;                             \
   589                 CLEAR_ERRNO;                         \
   587 		CLEAR_ERRNO;                         \
   590                 l = (cnt)-__offs;                    \
   588 		l = (cnt)-__offs;                    \
   591                 if ( l > IO_BUFFER_SIZE)             \
   589 		if ( l > IO_BUFFER_SIZE)             \
   592                     l = IO_BUFFER_SIZE;              \
   590 		    l = IO_BUFFER_SIZE;              \
   593                 if (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res)==0) { \
   591 		if (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res)==0) { \
   594                     if (res > 0) {                   \
   592 		    if (res > 0) {                   \
   595                         if (res > l)                 \
   593 			if (res > l)                 \
   596                             res = l;                 \
   594 			    res = l;                 \
   597                         READ(ret,f, __buf, res, handleType);     \
   595 			READ(ret,f, __buf, res, handleType);     \
   598                     } else {                         \
   596 		    } else {                         \
   599                         (ret) = 0;                   \
   597 			(ret) = 0;                   \
   600                     }                                \
   598 		    }                                \
   601                 } else if (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)) { \
   599 		} else if (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)) { \
   602                     if (res > 0) {                   \
   600 		    if (res > 0) {                   \
   603                         if (res > l)                 \
   601 			if (res > l)                 \
   604                             res = l;                 \
   602 			    res = l;                 \
   605                         READ(ret,f, __buf, res, handleType);     \
   603 			READ(ret,f, __buf, res, handleType);     \
   606                     } else                           \
   604 		    } else                           \
   607                         (ret) = 0;                   \
   605 			(ret) = 0;                   \
   608                 } else {                             \
   606 		} else {                             \
   609                     READ(ret,f, __buf, l, handleType);           \
   607 		    READ(ret,f, __buf, l, handleType);           \
   610                 }                                    \
   608 		}                                    \
   611                 if ((ret) < 0 && __threadErrno == EINTR) {   \
   609 		if ((ret) < 0 && __threadErrno == EINTR) {   \
   612                     continue;                        \
   610 		    continue;                        \
   613                 }                                    \
   611 		}                                    \
   614             }                                        \
   612 	    }                                        \
   615             if( (ret) > 0 ) {                               \
   613 	    if( (ret) > 0 ) {                               \
   616                 /* refetch */                               \
   614 		/* refetch */                               \
   617                 buf = (char *)(obj);               \
   615 		buf = (char *)(obj);               \
   618                 memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   616 		memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   619                 __offs += (ret);                            \
   617 		__offs += (ret);                            \
   620             } else {                                        \
   618 	    } else {                                        \
   621                 (ret) = 0;                                  \
   619 		(ret) = 0;                                  \
   622             }                                               \
   620 	    }                                               \
   623             break;                                      \
   621 	    break;                                      \
   624         }                                               \
   622 	}                                               \
   625         if (__offs > 0)                                 \
   623 	if (__offs > 0)                                 \
   626             (ret) = __offs;                             \
   624 	    (ret) = __offs;                             \
   627     }                                                   \
   625     }                                                   \
   628   }
   626   }
   629 
   627 
   630 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType)         \
   628 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType)         \
   631     if (isBuffered) {                                   \
   629     if (isBuffered) {                                   \
   632         for (;;) {                                      \
   630 	for (;;) {                                      \
   633             CLEAR_ERRNO;                                \
   631 	    CLEAR_ERRNO;                                \
   634             ret = putc(*(buf), f);                      \
   632 	    ret = putc(*(buf), f);                      \
   635             if ((ret) >= 0) {                           \
   633 	    if ((ret) >= 0) {                           \
   636                 (ret) = 1;                              \
   634 		(ret) = 1;                              \
   637             } else if (ferror(f)) {                     \
   635 	    } else if (ferror(f)) {                     \
   638                 if (__threadErrno == EINTR) {                   \
   636 		if (__threadErrno == EINTR) {                   \
   639                     clearerr(f);                        \
   637 		    clearerr(f);                        \
   640                     continue;                           \
   638 		    continue;                           \
   641                 }                                       \
   639 		}                                       \
   642             } else                                      \
   640 	    } else                                      \
   643                 (ret) = 0;                              \
   641 		(ret) = 0;                              \
   644             break;                                      \
   642 	    break;                                      \
   645         }                                               \
   643 	}                                               \
   646     } else {                                            \
   644     } else {                                            \
   647         for (;;) {                                      \
   645 	for (;;) {                                      \
   648             CLEAR_ERRNO;                                \
   646 	    CLEAR_ERRNO;                                \
   649             WRITE(ret,f, buf, 1, handleType);                       \
   647 	    WRITE(ret,f, buf, 1, handleType);                       \
   650             if ((ret) >= 0 || __threadErrno != EINTR)           \
   648 	    if ((ret) >= 0 || __threadErrno != EINTR)           \
   651                 break;                                  \
   649 		break;                                  \
   652         }                                               \
   650 	}                                               \
   653    }
   651    }
   654 
   652 
   655 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType)   \
   653 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType)   \
   656     (ret) = 0;                                          \
   654     (ret) = 0;                                          \
   657     if (isBuffered) {                                   \
   655     if (isBuffered) {                                   \
   658         int __offs = 0;                                 \
   656 	int __offs = 0;                                 \
   659         while (__offs < (cnt)) {                        \
   657 	while (__offs < (cnt)) {                        \
   660             CLEAR_ERRNO;                                \
   658 	    CLEAR_ERRNO;                                \
   661             (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\
   659 	    (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\
   662             if ((ret) <= 0) {                           \
   660 	    if ((ret) <= 0) {                           \
   663                 if (ferror(f)) {                        \
   661 		if (ferror(f)) {                        \
   664                     if (__threadErrno == EINTR) {               \
   662 		    if (__threadErrno == EINTR) {               \
   665                         clearerr(f);                    \
   663 			clearerr(f);                    \
   666                         continue;                       \
   664 			continue;                       \
   667                     }                                   \
   665 		    }                                   \
   668                     break;                              \
   666 		    break;                              \
   669                 } else {                                \
   667 		} else {                                \
   670                     (ret) = 0;                          \
   668 		    (ret) = 0;                          \
   671                 }                                       \
   669 		}                                       \
   672             }                                           \
   670 	    }                                           \
   673             __offs += (ret);                            \
   671 	    __offs += (ret);                            \
   674         }                                               \
   672 	}                                               \
   675         if (__offs > 0)                                 \
   673 	if (__offs > 0)                                 \
   676             (ret) = __offs;                             \
   674 	    (ret) = __offs;                             \
   677     } else {                                            \
   675     } else {                                            \
   678         int __offs = 0;                                 \
   676 	int __offs = 0;                                 \
   679         while (__offs < (cnt)) {                        \
   677 	while (__offs < (cnt)) {                        \
   680             CLEAR_ERRNO;                                \
   678 	    CLEAR_ERRNO;                                \
   681             WRITE(ret,f, (buf)+__offs, (cnt)-__offs, handleType);   \
   679 	    WRITE(ret,f, (buf)+__offs, (cnt)-__offs, handleType);   \
   682             if (ret <= 0) {                             \
   680 	    if (ret <= 0) {                             \
   683                 if (ret < 0 && __threadErrno == EINTR) {        \
   681 		if (ret < 0 && __threadErrno == EINTR) {        \
   684                     continue;                           \
   682 		    continue;                           \
   685                 }                                       \
   683 		}                                       \
   686                 break;                                  \
   684 		break;                                  \
   687             }                                           \
   685 	    }                                           \
   688             __offs += (ret);                            \
   686 	    __offs += (ret);                            \
   689         }                                               \
   687 	}                                               \
   690         if (__offs > 0)                                 \
   688 	if (__offs > 0)                                 \
   691             (ret) = __offs;                             \
   689 	    (ret) = __offs;                             \
   692    }
   690    }
   693 
   691 
   694 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \
   692 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \
   695   {                                                     \
   693   {                                                     \
   696     int __ooffs = obj_offs;                             \
   694     int __ooffs = obj_offs;                             \
   697     int __offs = 0;                                     \
   695     int __offs = 0;                                     \
   698     char *buf = (char *)(obj);                          \
   696     char *buf = (char *)(obj);                          \
   699                                                         \
   697 							\
   700     (ret) = 0;                                          \
   698     (ret) = 0;                                          \
   701     if (isBuffered) {                                   \
   699     if (isBuffered) {                                   \
   702         while (__offs < (cnt)) {                        \
   700 	while (__offs < (cnt)) {                        \
   703             CLEAR_ERRNO;                                \
   701 	    CLEAR_ERRNO;                                \
   704             ret = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f); \
   702 	    ret = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f); \
   705             if ((ret) <= 0) {                           \
   703 	    if ((ret) <= 0) {                           \
   706                 if (ferror(f)) {                        \
   704 		if (ferror(f)) {                        \
   707                     if (__threadErrno == EINTR) {       \
   705 		    if (__threadErrno == EINTR) {       \
   708                         /* refetch */                   \
   706 			/* refetch */                   \
   709                         buf = (char *)(obj);   \
   707 			buf = (char *)(obj);   \
   710                         clearerr(f);                    \
   708 			clearerr(f);                    \
   711                         continue;                       \
   709 			continue;                       \
   712                     }                                   \
   710 		    }                                   \
   713                     break;                              \
   711 		    break;                              \
   714                 } else {                                \
   712 		} else {                                \
   715                     (ret) = 0;                          \
   713 		    (ret) = 0;                          \
   716                 }                                       \
   714 		}                                       \
   717             }                                           \
   715 	    }                                           \
   718             __offs += (ret);                            \
   716 	    __offs += (ret);                            \
   719         }                                               \
   717 	}                                               \
   720         if (__offs > 0)                                 \
   718 	if (__offs > 0)                                 \
   721             (ret) = __offs;                             \
   719 	    (ret) = __offs;                             \
   722     } else {                                            \
   720     } else {                                            \
   723         while (__offs < (cnt)) {                        \
   721 	while (__offs < (cnt)) {                        \
   724             char __buf[IO_BUFFER_SIZE];                 \
   722 	    char __buf[IO_BUFFER_SIZE];                 \
   725             int l;                                      \
   723 	    int l;                                      \
   726             CLEAR_ERRNO;                                \
   724 	    CLEAR_ERRNO;                                \
   727             l = (cnt)-__offs;                           \
   725 	    l = (cnt)-__offs;                           \
   728             if ( l > IO_BUFFER_SIZE)                    \
   726 	    if ( l > IO_BUFFER_SIZE)                    \
   729               l = IO_BUFFER_SIZE;                       \
   727 	      l = IO_BUFFER_SIZE;                       \
   730             /* refetch */                               \
   728 	    /* refetch */                               \
   731             buf = (char *)(obj);               \
   729 	    buf = (char *)(obj);               \
   732             memcpy(__buf,(buf)+__ooffs+__offs,l);       \
   730 	    memcpy(__buf,(buf)+__ooffs+__offs,l);       \
   733             WRITE(ret,f, __buf, l, handleType);                     \
   731 	    WRITE(ret,f, __buf, l, handleType);                     \
   734             if (ret <= 0) {                             \
   732 	    if (ret <= 0) {                             \
   735                 if (ret < 0 && __threadErrno == EINTR) {        \
   733 		if (ret < 0 && __threadErrno == EINTR) {        \
   736                     continue;                           \
   734 		    continue;                           \
   737                 }                                       \
   735 		}                                       \
   738                 break;                                  \
   736 		break;                                  \
   739             }                                           \
   737 	    }                                           \
   740             __offs += (ret);                            \
   738 	    __offs += (ret);                            \
   741         }                                               \
   739 	}                                               \
   742         if (__offs > 0)                                 \
   740 	if (__offs > 0)                                 \
   743             (ret) = __offs;                             \
   741 	    (ret) = __offs;                             \
   744     }                                                   \
   742     }                                                   \
   745   }
   743   }
   746 
   744 
   747 #else /* no WIN32 */
   745 #else /* ! WIN32 */
   748 
   746 /* ========================   UNIX / LINUX ====================================================== */
   749 # define __READING__(f)                          \
   747 # define __READING__(f)                          \
   750     if ((__INST(didWrite) != false)              \
   748     if ((__INST(didWrite) != false)              \
   751      && (__INST(mode) == @symbol(readwrite))) {  \
   749      && (__INST(mode) == @symbol(readwrite))) {  \
   752         __INST(didWrite) = false;                \
   750 	__INST(didWrite) = false;                \
   753         OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   751 	OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   754     }
   752     }
   755 
   753 
   756 # define __WRITING__(f)                          \
   754 # define __WRITING__(f)                          \
   757     if ((__INST(didWrite) != true)               \
   755     if ((__INST(didWrite) != true)               \
   758      && (__INST(mode) == @symbol(readwrite))) {  \
   756      && (__INST(mode) == @symbol(readwrite))) {  \
   759         __INST(didWrite) = true;                 \
   757 	__INST(didWrite) = true;                 \
   760         OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   758 	OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */  \
   761     }
   759     }
   762 
   760 
   763 
   761 
   764 # ifdef NO_STDIO
   762 # ifdef NO_STDIO
   765 #  define __UNGETC__(c, f, isBuffered)                  \
   763 #  define __UNGETC__(c, f, isBuffered)                  \
   766     __INST(readAhead) = __mkSmallInteger((c));
   764     __INST(readAhead) = __mkSmallInteger((c));
   767 # else /* use STDIO */
   765 # else /* use STDIO */
   768 #  define __UNGETC__(c, f, isBuffered)                  \
   766 #  define __UNGETC__(c, f, isBuffered)                  \
   769     if (isBuffered) {                                   \
   767     if (isBuffered) {                                   \
   770         ungetc((c), (f));                               \
   768 	ungetc((c), (f));                               \
   771     } else {                                            \
   769     } else {                                            \
   772         __INST(readAhead) = __mkSmallInteger((c));          \
   770 	__INST(readAhead) = __mkSmallInteger((c));          \
   773     }
   771     }
   774 # endif /* use STDIO */
   772 # endif /* use STDIO */
   775 
   773 
   776 # ifdef NO_STDIO
   774 # ifdef NO_STDIO
   777 #  define __READBYTE__(ret, f, buf, isBuffered, handleType)         \
   775 #  define __READBYTE__(ret, f, buf, isBuffered, handleType)         \
   778     {                                                   \
   776     {                                                   \
   779         OBJ rA = __INST(readAhead);                     \
   777 	OBJ rA = __INST(readAhead);                     \
   780         if (rA != nil) {                                \
   778 	if (rA != nil) {                                \
   781             *(buf) = __intVal(rA);                      \
   779 	    *(buf) = __intVal(rA);                      \
   782             DEBUGBUFFER(buf);                           \
   780 	    DEBUGBUFFER(buf);                           \
   783             __INST(readAhead) = nil;                    \
   781 	    __INST(readAhead) = nil;                    \
   784             (ret) = 1;                                  \
   782 	    (ret) = 1;                                  \
   785         } else {                                        \
   783 	} else {                                        \
   786             for (;;) {                                  \
   784 	    for (;;) {                                  \
   787                 CLEAR_ERRNO;                            \
   785 		CLEAR_ERRNO;                            \
   788                 (ret) = READ(f, buf, 1, handleType);                \
   786 		(ret) = READ(f, buf, 1, handleType);    \
   789                 DEBUGBUFFER(buf);                       \
   787 		DEBUGBUFFER(buf);                       \
   790                 if ((ret) >= 0 || __threadErrno != EINTR)       \
   788 		if ((ret) >= 0) break;                  \
   791                     break;                              \
   789 		if (errno != EINTR) {                   \
   792                 __HANDLE_INTERRUPTS__;                  \
   790 		    break;                              \
   793             }                                           \
   791 		}                                       \
   794         }                                               \
   792 		__HANDLE_INTERRUPTS__;                  \
       
   793 	    }                                           \
       
   794 	}                                               \
   795     }
   795     }
   796 # else /* use STDIO */
   796 # else /* use STDIO */
   797 #  define __READBYTE__(ret, f, buf, isBuffered, handleType)         \
   797 #  define __READBYTE__(ret, f, buf, isBuffered, handleType)         \
   798     if (isBuffered) {                                   \
   798     if (isBuffered) {                                   \
   799         for (;;) {                                      \
   799 	for (;;) {                                      \
   800             CLEAR_ERRNO;                                \
   800 	    CLEAR_ERRNO;                                \
   801             (ret) = getc(f);                            \
   801 	    (ret) = getc(f);                            \
   802             if ((ret) >= 0) {                           \
   802 	    if ((ret) >= 0) {                           \
   803                 DEBUGBUFFER(buf);                       \
   803 		DEBUGBUFFER(buf);                       \
   804                 *(buf) = (ret);                         \
   804 		*(buf) = (ret);                         \
   805                 (ret) = 1;                              \
   805 		(ret) = 1;                              \
   806             } else if (ferror(f)) {                     \
   806 	    } else if (ferror(f)) {                     \
   807                 if (__threadErrno == EINTR) {                   \
   807 		if (errno == EINTR) {                   \
   808                     __HANDLE_INTERRUPTS__;              \
   808 		    __HANDLE_INTERRUPTS__;              \
   809                     clearerr(f);                        \
   809 		    clearerr(f);                        \
   810                     continue;                           \
   810 		    continue;                           \
   811                 }                                       \
   811 		}                                       \
   812             } else                                      \
   812 	    } else                                      \
   813                 (ret) = 0;                              \
   813 		(ret) = 0;                              \
   814             break;                                      \
   814 	    break;                                      \
   815         }                                               \
   815 	}                                               \
   816     } else {                                            \
   816     } else {                                            \
   817         OBJ rA = __INST(readAhead);                     \
   817 	OBJ rA = __INST(readAhead);                     \
   818         if (rA != nil) {                                \
   818 	if (rA != nil) {                                \
   819             *(buf) = __intVal(rA);                      \
   819 	    *(buf) = __intVal(rA);                      \
   820             DEBUGBUFFER(buf);                           \
   820 	    DEBUGBUFFER(buf);                           \
   821             __INST(readAhead) = nil;                    \
   821 	    __INST(readAhead) = nil;                    \
   822             (ret) = 1;                                  \
   822 	    (ret) = 1;                                  \
   823         } else {                                        \
   823 	} else {                                        \
   824             for (;;) {                                  \
   824 	    for (;;) {                                  \
   825                 CLEAR_ERRNO;                            \
   825 		CLEAR_ERRNO;                            \
   826                 (ret) = read(fileno(f), buf, 1);        \
   826 		(ret) = read(fileno(f), buf, 1);        \
   827                 DEBUGBUFFER(buf);                       \
   827 		DEBUGBUFFER(buf);                       \
   828                 if ((ret) >= 0 || __threadErrno != EINTR)       \
   828 		if ((ret) >= 0) break;                  \
   829                     break;                              \
   829 		if (errno != EINTR) {                   \
   830                 __HANDLE_INTERRUPTS__;                  \
   830 		    break;                              \
   831             }                                           \
   831 		}                                       \
   832         }                                               \
   832 		__HANDLE_INTERRUPTS__;                  \
       
   833 	    }                                           \
       
   834 	}                                               \
   833    }
   835    }
   834 # endif /* use STDIO */
   836 # endif /* use STDIO */
   835 
   837 
   836 /*
   838 /*
   837  * read_bytes into a c-buffer
   839  * read_bytes into a c-buffer
   838  * (which may NOT move)
   840  * (which may NOT move)
   839  */
   841  */
   840 # ifdef NO_STDIO
   842 # ifdef NO_STDIO
   841 #  define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType)   \
   843 #  define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType)   \
   842     {                                                   \
   844     {                                                   \
   843         int __offs = 0, __cnt;                          \
   845 	int __offs = 0, __cnt;                          \
   844                                                         \
   846 							\
   845         while (__offs < (cnt)) {                        \
   847 	while (__offs < (cnt)) {                        \
   846             OBJ rA = __INST(readAhead);                 \
   848 	    OBJ rA = __INST(readAhead);                 \
   847             if (rA != nil) {                            \
   849 	    if (rA != nil) {                            \
   848                 (buf)[__offs] = __intVal(rA);           \
   850 		(buf)[__offs] = __intVal(rA);           \
   849                 DEBUGBUFFER(buf);                       \
   851 		DEBUGBUFFER(buf);                       \
   850                 __INST(readAhead) = nil;                \
   852 		__INST(readAhead) = nil;                \
   851                 __offs++;                               \
   853 		__offs++;                               \
   852             } else {                                    \
   854 	    } else {                                    \
   853                 CLEAR_ERRNO;                            \
   855 		CLEAR_ERRNO;                            \
   854                 __cnt = READ(f, (buf)+__offs, (cnt)-__offs, handleType); \
   856 		__cnt = READ(f, (buf)+__offs, (cnt)-__offs, handleType); \
   855                 DEBUGBUFFER(buf);                       \
   857 		DEBUGBUFFER(buf);                       \
   856                 if (__cnt <= 0) {                       \
   858 		if (__cnt <= 0) {                       \
   857                     if (__cnt < 0 && __threadErrno == EINTR) {  \
   859 		    if (__cnt < 0 && errno == EINTR) {  \
   858                         __HANDLE_INTERRUPTS__;          \
   860 			__HANDLE_INTERRUPTS__;          \
   859                         continue;                       \
   861 			continue;                       \
   860                     }                                   \
   862 		    }                                   \
   861                     break;                              \
   863 		    break;                              \
   862                 }                                       \
   864 		}                                       \
   863                 __offs += __cnt;                        \
   865 		__offs += __cnt;                        \
   864             }                                           \
   866 	    }                                           \
   865         }                                               \
   867 	}                                               \
   866         if (__offs > 0)                                 \
   868 	if (__offs > 0)                                 \
   867             (ret) = __offs;                             \
   869 	    (ret) = __offs;                             \
   868    }
   870    }
   869 # else /* use STDIO */
   871 # else /* use STDIO */
   870 #  define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType)     \
   872 #  define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType)     \
   871     (ret) = 0;                                          \
   873     (ret) = 0;                                          \
   872     if (isBuffered) {                                   \
   874     if (isBuffered) {                                   \
   873         int __offs = 0;                                 \
   875 	int __offs = 0;                                 \
   874         while (__offs < (cnt)) {                        \
   876 	while (__offs < (cnt)) {                        \
   875             CLEAR_ERRNO;                                \
   877 	    CLEAR_ERRNO;                                \
   876             (ret) = getc(f);                            \
   878 	    (ret) = getc(f);                            \
   877             if ((ret) < 0) {                            \
   879 	    if ((ret) < 0) {                            \
   878                 if (ferror(f)) {                        \
   880 		if (ferror(f)) {                        \
   879                     if (__threadErrno == EINTR) {       \
   881 		    if (errno == EINTR) {               \
   880                         __HANDLE_INTERRUPTS__;          \
   882 			__HANDLE_INTERRUPTS__;          \
   881                         clearerr(f);                    \
   883 			clearerr(f);                    \
   882                         continue;                       \
   884 			continue;                       \
   883                     }                                   \
   885 		    }                                   \
   884                 } else {                                \
   886 		} else {                                \
   885                     (ret) = 0;                          \
   887 		    (ret) = 0;                          \
   886                 }                                       \
   888 		}                                       \
   887                 break;                                  \
   889 		break;                                  \
   888             }                                           \
   890 	    }                                           \
   889             DEBUGBUFFER(buf);                           \
   891 	    DEBUGBUFFER(buf);                           \
   890             (buf)[__offs++] = (ret);                    \
   892 	    (buf)[__offs++] = (ret);                    \
   891         }                                               \
   893 	}                                               \
   892         if (__offs > 0)                                 \
   894 	if (__offs > 0)                                 \
   893             (ret) = __offs;                             \
   895 	    (ret) = __offs;                             \
   894     } else {                                            \
   896     } else {                                            \
   895         int __offs = 0, __cnt;                          \
   897 	int __offs = 0, __cnt;                          \
   896         int fd = fileno(f);                             \
   898 	int fd = fileno(f);                             \
   897                                                         \
   899 							\
   898         while (__offs < (cnt)) {                        \
   900 	while (__offs < (cnt)) {                        \
   899             OBJ rA = __INST(readAhead);                 \
   901 	    OBJ rA = __INST(readAhead);                 \
   900             if (rA != nil) {                            \
   902 	    if (rA != nil) {                            \
   901                 DEBUGBUFFER(buf);                       \
   903 		DEBUGBUFFER(buf);                       \
   902                 (buf)[__offs] = __intVal(rA);           \
   904 		(buf)[__offs] = __intVal(rA);           \
   903                 __INST(readAhead) = nil;                \
   905 		__INST(readAhead) = nil;                \
   904                 __offs++;                               \
   906 		__offs++;                               \
   905             } else {                                    \
   907 	    } else {                                    \
   906                 CLEAR_ERRNO;                            \
   908 		CLEAR_ERRNO;                            \
   907                 __cnt = read(fd, (buf)+__offs, (cnt)-__offs);  \
   909 		__cnt = read(fd, (buf)+__offs, (cnt)-__offs);  \
   908                 DEBUGBUFFER(buf);                       \
   910 		DEBUGBUFFER(buf);                       \
   909                 if (__cnt <= 0) {                       \
   911 		if (__cnt <= 0) {                       \
   910                     if (__cnt < 0 && __threadErrno == EINTR) {  \
   912 		    if (__cnt < 0 && errno == EINTR) {  \
   911                         __HANDLE_INTERRUPTS__;          \
   913 			__HANDLE_INTERRUPTS__;          \
   912                         continue;                       \
   914 			continue;                       \
   913                     }                                   \
   915 		    }                                   \
   914                     break;                              \
   916 		    break;                              \
   915                 }                                       \
   917 		}                                       \
   916                 __offs += __cnt;                        \
   918 		__offs += __cnt;                        \
   917             }                                           \
   919 	    }                                           \
   918         }                                               \
   920 	}                                               \
   919         if (__offs > 0)                                 \
   921 	if (__offs > 0)                                 \
   920             (ret) = __offs;                             \
   922 	    (ret) = __offs;                             \
   921    }
   923    }
   922 
   924 
   923 
   925 
   924 /*
   926 /*
   925  * FNDELAY and O_NDELAY is deprecated, O_NONBLOCK is used in POSIX, XPG, etc...
   927  * FNDELAY and O_NDELAY is deprecated, O_NONBLOCK is used in POSIX, XPG, etc...
   926  */
   928  */
   927 
   929 
   928 #  if defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(O_NDELAY) || defined(FNDELAY))
   930 #  if defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(O_NDELAY) || defined(FNDELAY))
   929 #   define SETFLAGS(fd, flags) \
   931 #   define SETFLAGS(fd, flags) \
   930         fcntl(fd, F_SETFL, flags)
   932 	fcntl(fd, F_SETFL, flags)
   931 
   933 
   932 #   if defined(O_NONBLOCK)
   934 #   if defined(O_NONBLOCK)
   933 #    define __STX_NONBLOCK_FLAG O_NONBLOCK
   935 #    define __STX_NONBLOCK_FLAG O_NONBLOCK
   934 #   else
   936 #   else
   935 #    if defined(O_NDELAY)
   937 #    if defined(O_NDELAY)
   938 #     define __STX_NONBLOCK_FLAG FNDELAY
   940 #     define __STX_NONBLOCK_FLAG FNDELAY
   939 #    endif
   941 #    endif
   940 #   endif
   942 #   endif
   941 
   943 
   942 #   define SETNONBLOCKING(fd, oldFlags) \
   944 #   define SETNONBLOCKING(fd, oldFlags) \
   943         { \
   945 	{ \
   944             int flags = fcntl(fd, F_GETFL, 0); \
   946 	    int flags = fcntl(fd, F_GETFL, 0); \
   945             if (flags >= 0) { \
   947 	    if (flags >= 0) { \
   946                 fcntl(fd, F_SETFL, flags | __STX_NONBLOCK_FLAG); \
   948 		fcntl(fd, F_SETFL, flags | __STX_NONBLOCK_FLAG); \
   947             } \
   949 	    } \
   948             oldFlags = flags; \
   950 	    oldFlags = flags; \
   949         }
   951 	}
   950 #  else
   952 #  else
   951 #   define SETFLAGS(fd, flags) /* nothing */
   953 #   define SETFLAGS(fd, flags) /* nothing */
   952 #   define SETNONBLOCKING(fd, oldFlags) /* nothing */
   954 #   define SETNONBLOCKING(fd, oldFlags) /* nothing */
   953 #  endif
   955 #  endif
   954 
   956 
   955 #  define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \
   957 #  define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \
   956   {                                                     \
   958   {                                                     \
   957     int __offs = 0, __cnt;                              \
   959     int __offs = 0, __cnt;                              \
   958     int oldFlags;                                       \
   960     int oldFlags;                                       \
   959                                                         \
   961 							\
   960     (ret) = 0;                                          \
   962     (ret) = 0;                                          \
   961     SETNONBLOCKING(fileno(f), oldFlags);                \
   963     SETNONBLOCKING(fileno(f), oldFlags);                \
   962     if (isBuffered) {                                   \
   964     if (isBuffered) {                                   \
   963         while (__offs < (cnt)) {                        \
   965 	while (__offs < (cnt)) {                        \
   964             CLEAR_ERRNO;                                \
   966 	    CLEAR_ERRNO;                                \
   965             (ret) = getc(f);                            \
   967 	    (ret) = getc(f);                            \
   966             if ((ret) < 0) {                            \
   968 	    if ((ret) < 0) {                            \
   967                 if (ferror(f)) {                        \
   969 		if (ferror(f)) {                        \
   968                     if (__threadErrno == EINTR) {       \
   970 		    if (errno == EINTR) {               \
   969                         (ret) = 0;                      \
   971 			(ret) = 0;                      \
   970                         clearerr(f);                    \
   972 			clearerr(f);                    \
   971                         break;                          \
   973 			break;                          \
   972                     }                                   \
   974 		    }                                   \
   973                 } else {                                \
   975 		} else {                                \
   974                     (ret) = 0;                          \
   976 		    (ret) = 0;                          \
   975                 }                                       \
   977 		}                                       \
   976                 break;                                  \
   978 		break;                                  \
   977             }                                           \
   979 	    }                                           \
   978             (buf)[__offs++] = (ret);                    \
   980 	    (buf)[__offs++] = (ret);                    \
   979             DEBUGBUFFER(buf);                           \
   981 	    DEBUGBUFFER(buf);                           \
   980         }                                               \
   982 	}                                               \
   981         if (__offs > 0)                                 \
   983 	if (__offs > 0)                                 \
   982             (ret) = __offs;                             \
   984 	    (ret) = __offs;                             \
   983     } else {                                            \
   985     } else {                                            \
   984         int fd = fileno(f);                             \
   986 	int fd = fileno(f);                             \
   985                                                         \
   987 							\
   986         while (__offs < (cnt)) {                        \
   988 	while (__offs < (cnt)) {                        \
   987             OBJ rA = __INST(readAhead);                 \
   989 	    OBJ rA = __INST(readAhead);                 \
   988             if (rA != nil) {                            \
   990 	    if (rA != nil) {                            \
   989                 (buf)[__offs] = __intVal(rA);           \
   991 		(buf)[__offs] = __intVal(rA);           \
   990                 DEBUGBUFFER(buf);                       \
   992 		DEBUGBUFFER(buf);                       \
   991                 __INST(readAhead) = nil;                \
   993 		__INST(readAhead) = nil;                \
   992                 __offs++;                               \
   994 		__offs++;                               \
   993                 continue;                               \
   995 		continue;                               \
   994             }                                           \
   996 	    }                                           \
   995             CLEAR_ERRNO;                                \
   997 	    CLEAR_ERRNO;                                \
   996             __cnt = read(fd, (buf)+__offs, (cnt)-__offs); \
   998 	    __cnt = read(fd, (buf)+__offs, (cnt)-__offs); \
   997             DEBUGBUFFER(buf);                           \
   999 	    DEBUGBUFFER(buf);                           \
   998             if (__cnt > 0) {                            \
  1000 	    if (__cnt > 0) {                            \
   999                 __offs += __cnt;                        \
  1001 		__offs += __cnt;                        \
  1000             }                                           \
  1002 	    }                                           \
  1001             break;                                      \
  1003 	    break;                                      \
  1002         }                                               \
  1004 	}                                               \
  1003         if (__offs > 0)                                 \
  1005 	if (__offs > 0)                                 \
  1004             (ret) = __offs;                             \
  1006 	    (ret) = __offs;                             \
  1005     }                                                   \
  1007     }                                                   \
  1006     SETFLAGS(fileno(f), oldFlags);                      \
  1008     SETFLAGS(fileno(f), oldFlags);                      \
  1007   }
  1009   }
  1008 
  1010 
  1009 # endif /* use STDIO */
  1011 # endif /* use STDIO */
  1017   {                                                     \
  1019   {                                                     \
  1018     int __ooffs = obj_offs;                             \
  1020     int __ooffs = obj_offs;                             \
  1019     int __offs = 0;                                     \
  1021     int __offs = 0;                                     \
  1020     int __cnt;                                          \
  1022     int __cnt;                                          \
  1021     char *buf = (char *)(obj);                          \
  1023     char *buf = (char *)(obj);                          \
  1022                                                         \
  1024 							\
  1023     (ret) = 0;                                          \
  1025     (ret) = 0;                                          \
  1024     {                                                   \
  1026     {                                                   \
  1025         while (__offs < (cnt)) {                        \
  1027 	while (__offs < (cnt)) {                        \
  1026             OBJ rA = __INST(readAhead);                 \
  1028 	    OBJ rA = __INST(readAhead);                 \
  1027             if (rA != nil) {                            \
  1029 	    if (rA != nil) {                            \
  1028                 (buf)[__ooffs+__offs] = __intVal(rA);   \
  1030 		(buf)[__ooffs+__offs] = __intVal(rA);   \
  1029                 DEBUGBUFFER(buf);                       \
  1031 		DEBUGBUFFER(buf);                       \
  1030                 __INST(readAhead) = nil;                \
  1032 		__INST(readAhead) = nil;                \
  1031                 __offs++;                               \
  1033 		__offs++;                               \
  1032             } else {                                    \
  1034 	    } else {                                    \
  1033                 CLEAR_ERRNO;                            \
  1035 		CLEAR_ERRNO;                            \
  1034                 __cnt = READ(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \
  1036 		__cnt = READ(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \
  1035                 DEBUGBUFFER(buf);                       \
  1037 		DEBUGBUFFER(buf);                       \
  1036                 if (__cnt <= 0) {                       \
  1038 		if (__cnt <= 0) {                       \
  1037                     if (__cnt < 0 && __threadErrno == EINTR) {  \
  1039 		    if (__cnt < 0 && errno == EINTR) {  \
  1038                         __HANDLE_INTERRUPTS__;          \
  1040 			__HANDLE_INTERRUPTS__;          \
  1039                         /* refetch */                   \
  1041 			/* refetch */                   \
  1040                         buf = (char *)(obj);   \
  1042 			buf = (char *)(obj);            \
  1041                         continue;                       \
  1043 			continue;                       \
  1042                     }                                   \
  1044 		    }                                   \
  1043                     break;                              \
  1045 		    break;                              \
  1044                 }                                       \
  1046 		}                                       \
  1045                 __offs += __cnt;                        \
  1047 		__offs += __cnt;                        \
  1046             }                                           \
  1048 	    }                                           \
  1047         }                                               \
  1049 	}                                               \
  1048         if (__offs > 0)                                 \
  1050 	if (__offs > 0)                                 \
  1049             (ret) = __offs;                             \
  1051 	    (ret) = __offs;                             \
  1050     }                                                   \
  1052     }                                                   \
  1051   }
  1053   }
  1052 
  1054 
  1053 # else /* use STDIO */
  1055 # else /* use STDIO */
  1054 
  1056 
  1056   {                                                     \
  1058   {                                                     \
  1057     int __ooffs = obj_offs;                             \
  1059     int __ooffs = obj_offs;                             \
  1058     int __offs = 0;                                     \
  1060     int __offs = 0;                                     \
  1059     int __cnt;                                          \
  1061     int __cnt;                                          \
  1060     char *buf = (char *)(obj);                          \
  1062     char *buf = (char *)(obj);                          \
  1061                                                         \
  1063 							\
  1062     (ret) = 0;                                          \
  1064     (ret) = 0;                                          \
  1063     if (isBuffered) {                                   \
  1065     if (isBuffered) {                                   \
  1064         while (__offs < (cnt)) {                        \
  1066 	while (__offs < (cnt)) {                        \
  1065             CLEAR_ERRNO;                                \
  1067 	    CLEAR_ERRNO;                                \
  1066             (ret) = getc(f);                            \
  1068 	    (ret) = getc(f);                            \
  1067             if ((ret) < 0) {                            \
  1069 	    if ((ret) < 0) {                            \
  1068                 if (ferror(f)) {                        \
  1070 		if (ferror(f)) {                        \
  1069                     if (__threadErrno == EINTR) {       \
  1071 		    if (errno == EINTR) {               \
  1070                         __HANDLE_INTERRUPTS__;          \
  1072 			__HANDLE_INTERRUPTS__;          \
  1071                         clearerr(f);                    \
  1073 			clearerr(f);                    \
  1072                         /* refetch */                   \
  1074 			/* refetch */                   \
  1073                         buf = (char *)(obj);   \
  1075 			buf = (char *)(obj);            \
  1074                         DEBUGBUFFER(buf);               \
  1076 			DEBUGBUFFER(buf);               \
  1075                         continue;                       \
  1077 			continue;                       \
  1076                     }                                   \
  1078 		    }                                   \
  1077                 } else {                                \
  1079 		} else {                                \
  1078                     (ret) = 0;                          \
  1080 		    (ret) = 0;                          \
  1079                 }                                       \
  1081 		}                                       \
  1080                 break;                                  \
  1082 		break;                                  \
  1081             }                                           \
  1083 	    }                                           \
  1082             (buf)[__ooffs+__offs] = (ret);              \
  1084 	    (buf)[__ooffs+__offs] = (ret);              \
  1083             DEBUGBUFFER(buf);                           \
  1085 	    DEBUGBUFFER(buf);                           \
  1084             __offs++;                                   \
  1086 	    __offs++;                                   \
  1085         }                                               \
  1087 	}                                               \
  1086         if (__offs > 0)                                 \
  1088 	if (__offs > 0)                                 \
  1087             (ret) = __offs;                             \
  1089 	    (ret) = __offs;                             \
  1088     } else {                                            \
  1090     } else {                                            \
  1089         int fd = fileno(f);                             \
  1091 	int fd = fileno(f);                             \
  1090                                                         \
  1092 							\
  1091         while (__offs < (cnt)) {                        \
  1093 	while (__offs < (cnt)) {                        \
  1092             OBJ rA = __INST(readAhead);                 \
  1094 	    OBJ rA = __INST(readAhead);                 \
  1093             if (rA != nil) {                            \
  1095 	    if (rA != nil) {                            \
  1094                 (buf)[__ooffs+__offs] = __intVal(rA);   \
  1096 		(buf)[__ooffs+__offs] = __intVal(rA);   \
  1095                 DEBUGBUFFER(buf);                       \
  1097 		DEBUGBUFFER(buf);                       \
  1096                 __INST(readAhead) = nil;                \
  1098 		__INST(readAhead) = nil;                \
  1097                 __offs++;                               \
  1099 		__offs++;                               \
  1098             } else {                                    \
  1100 	    } else {                                    \
  1099                 CLEAR_ERRNO;                            \
  1101 		CLEAR_ERRNO;                            \
  1100                 __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \
  1102 		__cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \
  1101                 DEBUGBUFFER(buf);                       \
  1103 		DEBUGBUFFER(buf);                       \
  1102                 if (__cnt <= 0) {                       \
  1104 		if (__cnt <= 0) {                       \
  1103                     if (__cnt < 0 && __threadErrno == EINTR) {  \
  1105 		    if (__cnt < 0 && errno == EINTR) {  \
  1104                         __HANDLE_INTERRUPTS__;          \
  1106 			__HANDLE_INTERRUPTS__;          \
  1105                         /* refetch */                   \
  1107 			/* refetch */                   \
  1106                         buf = (char *)(obj);   \
  1108 			buf = (char *)(obj);            \
  1107                         continue;                       \
  1109 			continue;                       \
  1108                     }                                   \
  1110 		    }                                   \
  1109                     break;                              \
  1111 		    break;                              \
  1110                 }                                       \
  1112 		}                                       \
  1111                 __offs += __cnt;                        \
  1113 		__offs += __cnt;                        \
  1112             }                                           \
  1114 	    }                                           \
  1113         }                                               \
  1115 	}                                               \
  1114         if (__offs > 0)                                 \
  1116 	if (__offs > 0)                                 \
  1115             (ret) = __offs;                             \
  1117 	    (ret) = __offs;                             \
  1116     }                                                   \
  1118     }                                                   \
  1117   }
  1119   }
  1118 
  1120 
  1119 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)     \
  1121 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)     \
  1120   {                                                     \
  1122   {                                                     \
  1121     int __ooffs = obj_offs;                             \
  1123     int __ooffs = obj_offs;                             \
  1122     int __offs = 0;                                     \
  1124     int __offs = 0;                                     \
  1123     int __cnt;                                          \
  1125     int __cnt;                                          \
  1124     char *buf = (char *)(obj);                          \
  1126     char *buf = (char *)(obj);                          \
  1125     int oldFlags;                                       \
  1127     int oldFlags;                                       \
  1126                                                         \
  1128 							\
  1127     (ret) = 0;                                          \
  1129     (ret) = 0;                                          \
  1128     SETNONBLOCKING(fileno(f), oldFlags);                \
  1130     SETNONBLOCKING(fileno(f), oldFlags);                \
  1129                                                         \
  1131 							\
  1130     if (isBuffered) {                                   \
  1132     if (isBuffered) {                                   \
  1131         while (__offs < (cnt)) {                        \
  1133 	while (__offs < (cnt)) {                        \
  1132             CLEAR_ERRNO;                                \
  1134 	    CLEAR_ERRNO;                                \
  1133             (ret) = getc(f);                            \
  1135 	    (ret) = getc(f);                            \
  1134             if ((ret) < 0) {                            \
  1136 	    if ((ret) < 0) {                            \
  1135                 if (ferror(f)) {                        \
  1137 		if (ferror(f)) {                        \
  1136                     if (__threadErrno == EINTR) {       \
  1138 		    if (errno == EINTR) {               \
  1137                         clearerr(f);                    \
  1139 			clearerr(f);                    \
  1138                         /* refetch */                   \
  1140 			/* refetch */                   \
  1139                         buf = (char *)(obj);   \
  1141 			buf = (char *)(obj);            \
  1140                         (ret) = 0;                      \
  1142 			(ret) = 0;                      \
  1141                         break;                          \
  1143 			break;                          \
  1142                     }                                   \
  1144 		    }                                   \
  1143                 } else {                                \
  1145 		} else {                                \
  1144                     (ret) = 0;                          \
  1146 		    (ret) = 0;                          \
  1145                 }                                       \
  1147 		}                                       \
  1146                 break;                                  \
  1148 		break;                                  \
  1147             }                                           \
  1149 	    }                                           \
  1148             (buf)[__ooffs+__offs] = (ret);              \
  1150 	    (buf)[__ooffs+__offs] = (ret);              \
  1149             DEBUGBUFFER(buf);                           \
  1151 	    DEBUGBUFFER(buf);                           \
  1150             __offs++;                                   \
  1152 	    __offs++;                                   \
  1151         }                                               \
  1153 	}                                               \
  1152         if (__offs > 0)                                 \
  1154 	if (__offs > 0)                                 \
  1153             (ret) = __offs;                             \
  1155 	    (ret) = __offs;                             \
  1154     } else {                                            \
  1156     } else {                                            \
  1155         int fd = fileno(f);                             \
  1157 	int fd = fileno(f);                             \
  1156                                                         \
  1158 							\
  1157         while (__offs < (cnt)) {                        \
  1159 	while (__offs < (cnt)) {                        \
  1158             OBJ rA = __INST(readAhead);                 \
  1160 	    OBJ rA = __INST(readAhead);                 \
  1159             if (rA != nil) {                            \
  1161 	    if (rA != nil) {                            \
  1160                 (buf)[__ooffs+__offs] = __intVal(rA);   \
  1162 		(buf)[__ooffs+__offs] = __intVal(rA);   \
  1161                 DEBUGBUFFER(buf);                       \
  1163 		DEBUGBUFFER(buf);                       \
  1162                 __INST(readAhead) = nil;                \
  1164 		__INST(readAhead) = nil;                \
  1163                 __offs++;                               \
  1165 		__offs++;                               \
  1164                 continue;                               \
  1166 		continue;                               \
  1165             }                                           \
  1167 	    }                                           \
  1166             CLEAR_ERRNO;                                \
  1168 	    CLEAR_ERRNO;                                \
  1167             __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \
  1169 	    __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \
  1168             DEBUGBUFFER(buf);                           \
  1170 	    DEBUGBUFFER(buf);                           \
  1169             if (__cnt > 0) {                            \
  1171 	    if (__cnt > 0) {                            \
  1170                 __offs += __cnt;                        \
  1172 		__offs += __cnt;                        \
  1171             }                                           \
  1173 	    }                                           \
  1172             break;                                      \
  1174 	    break;                                      \
  1173         }                                               \
  1175 	}                                               \
  1174         if (__offs > 0)                                 \
  1176 	if (__offs > 0)                                 \
  1175             (ret) = __offs;                             \
  1177 	    (ret) = __offs;                             \
  1176     }                                                   \
  1178     }                                                   \
  1177     SETFLAGS(fileno(f), oldFlags);                      \
  1179     SETFLAGS(fileno(f), oldFlags);                      \
  1178   }
  1180   }
  1179 
  1181 
  1180 
  1182 
  1181 # endif /* use STDIO */
  1183 # endif /* use STDIO */
  1182 
  1184 
  1183 # ifdef NO_STDIO
  1185 # ifdef NO_STDIO
  1184 #  define __WRITEBYTE__(ret, f, buf, isBuffered, handleType)          \
  1186 #  define __WRITEBYTE__(ret, f, buf, isBuffered, handleType)          \
  1185         for (;;) {                                      \
  1187 	for (;;) {                                      \
  1186             CLEAR_ERRNO;                                \
  1188 	    CLEAR_ERRNO;                                \
  1187             (ret) = WRITE(f, buf, 1, handleType);                   \
  1189 	    (ret) = WRITE(f, buf, 1, handleType);       \
  1188             if ((ret) >= 0 || __threadErrno != EINTR)           \
  1190 	    if ((ret) >= 0) break;                      \
  1189                 break;                                  \
  1191 	    if (errno != EINTR) {                       \
  1190             __HANDLE_INTERRUPTS__;                      \
  1192 		break;                                  \
  1191         }
  1193 	    }                                           \
       
  1194 	    __HANDLE_INTERRUPTS__;                      \
       
  1195 	}
  1192 # else /* use STDIO */
  1196 # else /* use STDIO */
  1193 #  define __WRITEBYTE__(ret, f, buf, isBuffered, handleType)        \
  1197 #  define __WRITEBYTE__(ret, f, buf, isBuffered, handleType)        \
  1194     if (isBuffered) {                                   \
  1198     if (isBuffered) {                                   \
  1195         for (;;) {                                      \
  1199 	for (;;) {                                      \
  1196             CLEAR_ERRNO;                                \
  1200 	    CLEAR_ERRNO;                                \
  1197             ret = putc(*(buf), f);                      \
  1201 	    ret = putc(*(buf), f);                      \
  1198             if ((ret) >= 0) {                           \
  1202 	    if ((ret) >= 0) {                           \
  1199                 (ret) = 1;                              \
  1203 		(ret) = 1;                              \
  1200             } else if (ferror(f)) {                     \
  1204 	    } else if (ferror(f)) {                     \
  1201                 /* SOLARIS/SPARC (2.6) generates spurious errors with errno = 0 */ \
  1205 		/* SOLARIS/SPARC (2.6) generates spurious errors with errno = 0 */ \
  1202                 if (__threadErrno == EINTR || __threadErrno == 0) {     \
  1206 		if (errno == EINTR || errno == 0) {     \
  1203                     __HANDLE_INTERRUPTS__;              \
  1207 		    __HANDLE_INTERRUPTS__;              \
  1204                     clearerr(f);                        \
  1208 		    clearerr(f);                        \
  1205                     continue;                           \
  1209 		    continue;                           \
  1206                 }                                       \
  1210 		}                                       \
  1207             } else                                      \
  1211 	    } else                                      \
  1208                 (ret) = 0;                              \
  1212 		(ret) = 0;                              \
  1209             break;                                      \
  1213 	    break;                                      \
  1210         }                                               \
  1214 	}                                               \
  1211     } else {                                            \
  1215     } else {                                            \
  1212         for (;;) {                                      \
  1216 	for (;;) {                                      \
  1213             CLEAR_ERRNO;                                \
  1217 	    CLEAR_ERRNO;                                \
  1214             (ret) = write(fileno(f), buf, 1);           \
  1218 	    (ret) = write(fileno(f), buf, 1);           \
  1215             if ((ret) >= 0 || __threadErrno != EINTR)           \
  1219 	    if ((ret) >= 0) break;                      \
  1216                 break;                                  \
  1220 	    if (errno != EINTR) {                       \
  1217             __HANDLE_INTERRUPTS__;                      \
  1221 		break;                                  \
  1218         }                                               \
  1222 	    }                                           \
       
  1223 	    __HANDLE_INTERRUPTS__;                      \
       
  1224 	}                                               \
  1219    }
  1225    }
  1220 # endif /* use STDIO */
  1226 # endif /* use STDIO */
  1221 
  1227 
  1222 /*
  1228 /*
  1223  * write_bytes from a c-buffer
  1229  * write_bytes from a c-buffer
  1225  */
  1231  */
  1226 # ifdef NO_STDIO
  1232 # ifdef NO_STDIO
  1227 #  define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType)    \
  1233 #  define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType)    \
  1228     (ret) = 0;                                          \
  1234     (ret) = 0;                                          \
  1229     {                                                   \
  1235     {                                                   \
  1230         int __offs = 0;                                 \
  1236 	int __offs = 0;                                 \
  1231         while (__offs < (cnt)) {                        \
  1237 	while (__offs < (cnt)) {                        \
  1232             CLEAR_ERRNO;                                \
  1238 	    CLEAR_ERRNO;                                \
  1233             ret = WRITE(f, (buf)+__offs, (cnt)-__offs, handleType); \
  1239 	    ret = WRITE(f, (buf)+__offs, (cnt)-__offs, handleType); \
  1234             if (ret <= 0) {                             \
  1240 	    if (ret <= 0) {                             \
  1235                 if (ret < 0 && __threadErrno == EINTR) {        \
  1241 		if (ret < 0 && errno == EINTR) {        \
  1236                     __HANDLE_INTERRUPTS__;              \
  1242 		    __HANDLE_INTERRUPTS__;              \
  1237                     continue;                           \
  1243 		    continue;                           \
  1238                 }                                       \
  1244 		}                                       \
  1239                 break;                                  \
  1245 		break;                                  \
  1240             }                                           \
  1246 	    }                                           \
  1241             __offs += (ret);                            \
  1247 	    __offs += (ret);                            \
  1242         }                                               \
  1248 	}                                               \
  1243         if (__offs > 0)                                 \
  1249 	if (__offs > 0)                                 \
  1244             (ret) = __offs;                             \
  1250 	    (ret) = __offs;                             \
  1245    }
  1251    }
  1246 # else /* use STDIO */
  1252 # else /* use STDIO */
  1247 #  define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType)    \
  1253 #  define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType)    \
  1248     (ret) = 0;                                          \
  1254     (ret) = 0;                                          \
  1249     if (isBuffered) {                                   \
  1255     if (isBuffered) {                                   \
  1250         int __offs = 0;                                 \
  1256 	int __offs = 0;                                 \
  1251         while (__offs < (cnt)) {                        \
  1257 	while (__offs < (cnt)) {                        \
  1252             CLEAR_ERRNO;                                \
  1258 	    CLEAR_ERRNO;                                \
  1253             (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\
  1259 	    (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\
  1254             if ((ret) <= 0) {                            \
  1260 	    if ((ret) <= 0) {                            \
  1255                 if (ferror(f)) {                        \
  1261 		if (ferror(f)) {                        \
  1256                     if (__threadErrno == EINTR) {       \
  1262 		    if (errno == EINTR) {               \
  1257                         __HANDLE_INTERRUPTS__;          \
  1263 			__HANDLE_INTERRUPTS__;          \
  1258                         clearerr(f);                    \
  1264 			clearerr(f);                    \
  1259                         continue;                       \
  1265 			continue;                       \
  1260                     }                                   \
  1266 		    }                                   \
  1261                     (ret) = __offs = -1;                \
  1267 		} else {                                \
  1262                 } else {                                \
  1268 		    (ret) = 0;                          \
  1263                     (ret) = 0;                          \
  1269 		}                                       \
  1264                 }                                       \
  1270 		break;                                  \
  1265                 break;                                  \
  1271 	    }                                           \
  1266             }                                           \
  1272 	    __offs += (ret);                            \
  1267             __offs += (ret);                            \
  1273 	}                                               \
  1268         }                                               \
  1274 	if (__offs > 0)                                 \
  1269         if (__offs > 0)                                 \
  1275 	    (ret) = __offs;                             \
  1270             (ret) = __offs;                             \
       
  1271     } else {                                            \
  1276     } else {                                            \
  1272         int __offs = 0;                                 \
  1277 	int __offs = 0;                                 \
  1273         while (__offs < (cnt)) {                        \
  1278 	while (__offs < (cnt)) {                        \
  1274             CLEAR_ERRNO;                                \
  1279 	    CLEAR_ERRNO;                                \
  1275             (ret) = write(fileno(f), (buf)+__offs, (cnt)-__offs);\
  1280 	    (ret) = write(fileno(f), (buf)+__offs, (cnt)-__offs);\
  1276             if ((ret) <= 0) {                           \
  1281 	    if ((ret) <= 0) {                           \
  1277                 if ((ret) < 0) {                        \
  1282 		if ((ret) < 0) {                        \
  1278                     if (__threadErrno == EINTR) {       \
  1283 		    if (errno == EINTR) {               \
  1279                         __HANDLE_INTERRUPTS__;          \
  1284 			__HANDLE_INTERRUPTS__;          \
  1280                         continue;                       \
  1285 			continue;                       \
  1281                     }                                   \
  1286 		    }                                   \
  1282                     (ret) = __offs = -1;                \
  1287 		}                                       \
  1283                 }                                       \
  1288 		break;                                  \
  1284                 break;                                  \
  1289 	    }                                           \
  1285             }                                           \
  1290 	    __offs += (ret);                            \
  1286             __offs += (ret);                            \
  1291 	}                                               \
  1287         }                                               \
  1292 	if (__offs > 0)                                 \
  1288         if (__offs > 0)                                 \
  1293 	    (ret) = __offs;                             \
  1289             (ret) = __offs;                             \
       
  1290    }
  1294    }
  1291 # endif /* use STDIO */
  1295 # endif /* use STDIO */
  1292 
  1296 
  1293 /*
  1297 /*
  1294  * write_bytes from an object
  1298  * write_bytes from an object
  1298 #  define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)            \
  1302 #  define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)            \
  1299   {                                                     \
  1303   {                                                     \
  1300     int __ooffs = obj_offs;                             \
  1304     int __ooffs = obj_offs;                             \
  1301     int __offs = 0;                                     \
  1305     int __offs = 0;                                     \
  1302     char *buf = (char *)(obj);                          \
  1306     char *buf = (char *)(obj);                          \
  1303                                                         \
  1307 							\
  1304     (ret) = 0;                                          \
  1308     (ret) = 0;                                          \
  1305     {                                                   \
  1309     {                                                   \
  1306         while (__offs < (cnt)) {                        \
  1310 	while (__offs < (cnt)) {                        \
  1307             CLEAR_ERRNO;                                \
  1311 	    CLEAR_ERRNO;                                \
  1308             ret = WRITE(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \
  1312 	    ret = WRITE(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \
  1309             if (ret <= 0) {                             \
  1313 	    if (ret <= 0) {                             \
  1310                 if (ret < 0 && __threadErrno == EINTR) { \
  1314 		if (ret < 0 && errno == EINTR) {        \
  1311                     __HANDLE_INTERRUPTS__;              \
  1315 		    __HANDLE_INTERRUPTS__;              \
  1312                     /* refetch */                       \
  1316 		    /* refetch */                       \
  1313                     buf = (char *)(obj);                \
  1317 		    buf = (char *)(obj);                \
  1314                     continue;                           \
  1318 		    continue;                           \
  1315                 }                                       \
  1319 		}                                       \
  1316                 break;                                  \
  1320 		break;                                  \
  1317             }                                           \
  1321 	    }                                           \
  1318             __offs += (ret);                            \
  1322 	    __offs += (ret);                            \
  1319         }                                               \
  1323 	}                                               \
  1320         if (__offs > 0)                                 \
  1324 	if (__offs > 0)                                 \
  1321             (ret) = __offs;                             \
  1325 	    (ret) = __offs;                             \
  1322     }                                                   \
  1326     }                                                   \
  1323   }
  1327   }
  1324 # else /* use STDIO */
  1328 # else /* use STDIO */
  1325 #  define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)            \
  1329 #  define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)            \
  1326   {                                                     \
  1330   {                                                     \
  1327     int __ooffs = obj_offs;                             \
  1331     int __ooffs = obj_offs;                             \
  1328     int __offs = 0;                                     \
  1332     int __offs = 0;                                     \
  1329     char *buf = (char *)(obj);                          \
  1333     char *buf = (char *)(obj);                          \
  1330                                                         \
  1334 							\
  1331     (ret) = 0;                                          \
  1335     (ret) = 0;                                          \
  1332     if (isBuffered) {                                   \
  1336     if (isBuffered) {                                   \
  1333         while (__offs < (cnt)) {                        \
  1337 	while (__offs < (cnt)) {                        \
  1334             CLEAR_ERRNO;                                \
  1338 	    CLEAR_ERRNO;                                \
  1335             (ret) = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f);  \
  1339 	    (ret) = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f);  \
  1336             if ((ret) <= 0) {                           \
  1340 	    if ((ret) <= 0) {                           \
  1337                 if (ferror(f)) {                        \
  1341 		if (ferror(f)) {                        \
  1338                     if (__threadErrno == EINTR) {       \
  1342 		    if (errno == EINTR) {               \
  1339                         __HANDLE_INTERRUPTS__;          \
  1343 			__HANDLE_INTERRUPTS__;          \
  1340                         /* refetch */                   \
  1344 			/* refetch */                   \
  1341                         buf = (char *)(obj);            \
  1345 			buf = (char *)(obj);            \
  1342                         clearerr(f);                    \
  1346 			clearerr(f);                    \
  1343                         continue;                       \
  1347 			continue;                       \
  1344                     }                                   \
  1348 		    }                                   \
  1345                     (ret) = __offs = -1;                \
  1349 		    break;                              \
  1346                     break;                              \
  1350 		} else {                                \
  1347                 } else {                                \
  1351 		    (ret) = 0;                          \
  1348                     (ret) = 0;                          \
  1352 		}                                       \
  1349                 }                                       \
  1353 	    }                                           \
  1350             }                                           \
  1354 	    __offs += (ret);                            \
  1351             __offs += (ret);                            \
  1355 	}                                               \
  1352         }                                               \
       
  1353     } else {                                            \
  1356     } else {                                            \
  1354         while (__offs < (cnt)) {                        \
  1357 	while (__offs < (cnt)) {                        \
  1355             CLEAR_ERRNO;                                \
  1358 	    CLEAR_ERRNO;                                \
  1356             (ret) = write(fileno(f), (buf)+__ooffs+__offs, (cnt)-__offs); \
  1359 	    (ret) = write(fileno(f), (buf)+__ooffs+__offs, (cnt)-__offs); \
  1357             if ((ret) <= 0) {                           \
  1360 	    if ((ret) <= 0) {                           \
  1358                 if ((ret) < 0) {                        \
  1361 		if ((ret) < 0) {                        \
  1359                     if (__threadErrno == EINTR){        \
  1362 		    if (errno == EINTR){                \
  1360                         __HANDLE_INTERRUPTS__;          \
  1363 			__HANDLE_INTERRUPTS__;          \
  1361                         /* refetch */                   \
  1364 			/* refetch */                   \
  1362                         buf = (char *)(obj);            \
  1365 			buf = (char *)(obj);            \
  1363                         continue;                       \
  1366 			continue;                       \
  1364                     }                                   \
  1367 		    }                                   \
  1365                     (ret) = __offs = -1;                \
  1368 		}                                       \
  1366                 }                                       \
  1369 		break;                                  \
  1367                 break;                                  \
  1370 	    }                                           \
  1368             }                                           \
  1371 	    __offs += (ret); break;                     \
  1369             __offs += (ret); break;                     \
  1372 	}                                               \
  1370         }                                               \
       
  1371     }                                                   \
  1373     }                                                   \
  1372     if (__offs > 0)                                     \
  1374     if (__offs > 0)                                     \
  1373         (ret) = __offs;                                 \
  1375 	(ret) = __offs;                                 \
  1374   }
  1376   }
  1375 # endif /* use STDIO */
  1377 # endif /* use STDIO */
  1376 #endif /* unix */
  1378 #endif /* unix */
  1377 
       
  1378 /*
       
  1379  * on some systems errno is a macro ... check for it here
       
  1380  */
       
  1381 #ifndef errno
       
  1382  extern errno;
       
  1383 #endif
       
  1384 
       
  1385 %}
  1379 %}
  1386 ! !
  1380 ! !
  1387 
  1381 
  1388 !ExternalStream class methodsFor:'documentation'!
  1382 !ExternalStream class methodsFor:'documentation'!
  1389 
  1383 
  2410 
  2404 
  2411     "Modified: / 8.5.1999 / 20:12:20 / cg"
  2405     "Modified: / 8.5.1999 / 20:12:20 / cg"
  2412 !
  2406 !
  2413 
  2407 
  2414 ioError
  2408 ioError
  2415     "{ Pragma: +optSpace }"
       
  2416 
       
  2417     "report an error, that some I/O error occured.
  2409     "report an error, that some I/O error occured.
  2418      (for example, a device-IO-error, or reading an NFS-dir,
  2410      (for example, a device-IO-error, or reading an NFS-dir,
  2419      which is no longer available and has been mounted soft)"
  2411      which is no longer available and has been mounted soft)"
  2420 
  2412 
  2421     ^ StreamIOError
  2413     "{ Pragma: +optSpace }"
  2422 	raiseRequestWith:self
  2414 
  2423 	errorString:(' : ' , self lastErrorString)
  2415     self ioError:lastErrorNumber
  2424 	"/ in:thisContext sender
  2416 
       
  2417     "Modified: / 8.5.1999 / 20:12:16 / cg"
       
  2418 !
       
  2419 
       
  2420 ioError:errorNumber
       
  2421     "report an error, that some I/O error occured.
       
  2422      (for example, a device-IO-error, or reading an NFS-dir,
       
  2423      which is no longer available and has been mounted soft)"
       
  2424 
       
  2425     "{ Pragma: +optSpace }"
       
  2426 
       
  2427     ^ StreamIOError newException
       
  2428 	errorCode:errorNumber;
       
  2429 	osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber);
       
  2430 	parameter:self;
       
  2431 	raiseRequest
  2425 
  2432 
  2426     "Modified: / 8.5.1999 / 20:12:16 / cg"
  2433     "Modified: / 8.5.1999 / 20:12:16 / cg"
  2427 !
  2434 !
  2428 
  2435 
  2429 lastErrorNumber
  2436 lastErrorNumber
  2463     |exClass errorHolder|
  2470     |exClass errorHolder|
  2464 
  2471 
  2465     errorHolder := OperatingSystem errorHolderForNumber:errorNumber.
  2472     errorHolder := OperatingSystem errorHolderForNumber:errorNumber.
  2466 
  2473 
  2467     exClass := (errorHolder errorCategory == #nonexistentSignal)
  2474     exClass := (errorHolder errorCategory == #nonexistentSignal)
  2468         ifTrue:[ FileDoesNotExistException ]
  2475 	ifTrue:[ FileDoesNotExistException ]
  2469         ifFalse:[ OpenError ].
  2476 	ifFalse:[ OpenError ].
  2470 
  2477 
  2471     ^ exClass newException
  2478     ^ exClass newException
  2472         errorCode:errorNumber;
  2479 	errorCode:errorNumber;
  2473         osErrorHolder:errorHolder;
  2480 	osErrorHolder:errorHolder;
  2474         "/ cg: initialized lazyly - see OpenError>>#description
  2481 	"/ cg: initialized lazyly - see OpenError>>#description
  2475         "/ errorString:(' : ' , errorHolder errorString);
  2482 	"/ errorString:(' : ' , errorHolder errorString);
  2476         parameter:self;
  2483 	parameter:self;
  2477         raiseRequest
  2484 	raiseRequest
  2478         "/ in:thisContext sender
  2485 	"/ in:thisContext sender
  2479 
  2486 
  2480     "Modified: / 09-09-2011 / 07:22:49 / cg"
  2487     "Modified: / 09-09-2011 / 07:22:49 / cg"
  2481 !
  2488 !
  2482 
  2489 
  2483 readError
  2490 readError
  2492     "report an error, that some read error occured"
  2499     "report an error, that some read error occured"
  2493 
  2500 
  2494     "{ Pragma: +optSpace }"
  2501     "{ Pragma: +optSpace }"
  2495 
  2502 
  2496     ^ ReadError newException
  2503     ^ ReadError newException
  2497         errorCode:lastErrorNumber;
  2504 	errorCode:errorNumber;
  2498         osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber);
  2505 	osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber);
  2499         parameter:self;
  2506 	parameter:self;
  2500         raiseRequest
  2507 	raiseRequest
  2501 !
  2508 !
  2502 
  2509 
  2503 writeError
  2510 writeError
  2504     "report an error, that some write error occured"
  2511     "report an error, that some write error occured"
  2505 
  2512 
  2512     "report an error, that some write error occured"
  2519     "report an error, that some write error occured"
  2513 
  2520 
  2514     "{ Pragma: +optSpace }"
  2521     "{ Pragma: +optSpace }"
  2515 
  2522 
  2516     ^ WriteError newException
  2523     ^ WriteError newException
  2517         errorCode:lastErrorNumber;
  2524 	errorCode:errorNumber;
  2518         osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber);
  2525 	osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber);
  2519         parameter:self;
  2526 	parameter:self;
  2520         raiseRequest
  2527 	raiseRequest
  2521 ! !
  2528 ! !
  2522 
  2529 
  2523 !ExternalStream methodsFor:'finalization'!
  2530 !ExternalStream methodsFor:'finalization'!
  2524 
  2531 
  2525 executor
  2532 executor
  2560      Return a string containing those characters excluding the newline.
  2567      Return a string containing those characters excluding the newline.
  2561      If the previous-to-last character is a cr, this is also removed,
  2568      If the previous-to-last character is a cr, this is also removed,
  2562      so its possible to read alien (i.e. ms-dos) text as well.
  2569      so its possible to read alien (i.e. ms-dos) text as well.
  2563      The line must be shorter than 32K characters - otherwise an error is signalled."
  2570      The line must be shorter than 32K characters - otherwise an error is signalled."
  2564 
  2571 
  2565     |line|
  2572     |line error|
  2566 
  2573 
  2567 %{  /* STACK:100000 */
  2574 %{  /* STACK:100000 */
  2568 
  2575 
  2569     FILEPOINTER f;
  2576     FILEPOINTER f;
  2570     int len, ret;
  2577     int len, ret;
  2603 			rslt = NULL;
  2610 			rslt = NULL;
  2604 		    if (ret == 0) {
  2611 		    if (ret == 0) {
  2605 			__INST(hitEOF) = true;
  2612 			__INST(hitEOF) = true;
  2606 			break;
  2613 			break;
  2607 		    } else {
  2614 		    } else {
  2608 			__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  2615 			error = __mkSmallInteger(__threadErrno);
  2609 			goto err;
  2616 			goto err;
  2610 		    }
  2617 		    }
  2611 		}
  2618 		}
  2612 
  2619 
  2613 		if (*nextPtr == '\n') {
  2620 		if (*nextPtr == '\n') {
  2627 			*nextPtr = '\0';
  2634 			*nextPtr = '\0';
  2628 			if (ret == 0) {
  2635 			if (ret == 0) {
  2629 			    __INST(hitEOF) = true;
  2636 			    __INST(hitEOF) = true;
  2630 			    break;
  2637 			    break;
  2631 			}
  2638 			}
  2632 			__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  2639 			error = __mkSmallInteger(__threadErrno);
  2633 			goto err;
  2640 			goto err;
  2634 		    }
  2641 		    }
  2635 
  2642 
  2636 		    if (peekChar == '\n') {
  2643 		    if (peekChar == '\n') {
  2637 			cutOff = 2;
  2644 			cutOff = 2;
  2699 	].
  2706 	].
  2700 	^ line , self nextLine
  2707 	^ line , self nextLine
  2701     ].
  2708     ].
  2702 
  2709 
  2703     (hitEOF == true) ifTrue:[^ self pastEndRead].
  2710     (hitEOF == true) ifTrue:[^ self pastEndRead].
  2704     lastErrorNumber notNil ifTrue:[^ self readError].
  2711     error notNil ifTrue:[
       
  2712 	lastErrorNumber := error.
       
  2713 	^ self readError:error
       
  2714     ].
  2705     handle isNil ifTrue:[^ self errorNotOpen].
  2715     handle isNil ifTrue:[^ self errorNotOpen].
  2706     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  2716     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  2707     (binary == true) ifTrue:[^ self errorBinary].
  2717     (binary == true) ifTrue:[^ self errorBinary].
  2708     ^ super nextLine
  2718     ^ super nextLine
  2709 !
  2719 !
  2710 
  2720 
  2711 nextPutLine:aString
  2721 nextPutLine:aString
  2712     "write the characters in aString and append an end-of-Line marker
  2722     "write the characters in aString and append an end-of-Line marker
  2713      (LF, CR or CRLF - depending in the setting of eolMode)"
  2723      (LF, CR or CRLF - depending in the setting of eolMode)"
  2714 
  2724 
       
  2725     |error|
  2715 %{
  2726 %{
  2716     FILEPOINTER f;
  2727     FILEPOINTER f;
  2717     int len, cnt, len1, _buffered;
  2728     int len, cnt, len1, _buffered;
  2718     OBJ fp;
  2729     OBJ fp;
  2719     char *cp;
  2730     char *cp;
  2774 			__INST(position) = nil; /* i.e. do not know */
  2785 			__INST(position) = nil; /* i.e. do not know */
  2775 		    }
  2786 		    }
  2776 		    RETURN ( self );
  2787 		    RETURN ( self );
  2777 		}
  2788 		}
  2778 	    }
  2789 	    }
  2779 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  2790 	    error = __mkSmallInteger(__threadErrno);
  2780 	}
  2791 	}
  2781     }
  2792     }
  2782 %}.
  2793 %}.
       
  2794     error notNil ifTrue:[
       
  2795 	lastErrorNumber := error.
       
  2796 	self writeError:error.
       
  2797 	^ self
       
  2798     ].
  2783     super nextPutLine:aString.
  2799     super nextPutLine:aString.
  2784 !
  2800 !
  2785 
  2801 
  2786 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil
  2802 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil
  2787     "read from aStream up to and including a line starting with aStringOrNil
  2803     "read from aStream up to and including a line starting with aStringOrNil
  2914     "copy the data into another stream."
  2930     "copy the data into another stream."
  2915 
  2931 
  2916     |bufferSize|
  2932     |bufferSize|
  2917 
  2933 
  2918     OperatingSystem isMSDOSlike ifTrue:[
  2934     OperatingSystem isMSDOSlike ifTrue:[
  2919         "/ mhmh - NT hangs, when copying bigger blocks to a network drive - why ?
  2935 	"/ mhmh - NT hangs, when copying bigger blocks to a network drive - why ?
  2920         bufferSize := 1 * 1024.
  2936 	bufferSize := 1 * 1024.
  2921     ] ifFalse:[
  2937     ] ifFalse:[
  2922         bufferSize := 8 * 1024.
  2938 	bufferSize := 8 * 1024.
  2923     ].
  2939     ].
  2924 
  2940 
  2925     ^ self copyToEndInto:outStream bufferSize:bufferSize
  2941     ^ self copyToEndInto:outStream bufferSize:bufferSize
  2926 
  2942 
  2927     "
  2943     "
  3003 			ioArg = (INT)(__externalAddressVal(arg));
  3019 			ioArg = (INT)(__externalAddressVal(arg));
  3004 		    } else {
  3020 		    } else {
  3005 			ioArg = (INT)(__ByteArrayInstPtr(arg)->ba_element);
  3021 			ioArg = (INT)(__ByteArrayInstPtr(arg)->ba_element);
  3006 		    }
  3022 		    }
  3007 		    ret = ioctl(fileno(f), ioNum, ioArg);
  3023 		    ret = ioctl(fileno(f), ioNum, ioArg);
  3008 		} while ((ret < 0) && (__threadErrno == EINTR));
  3024 		} while (ret < 0 && __threadErrno == EINTR);
  3009 		__END_INTERRUPTABLE__
  3025 		__END_INTERRUPTABLE__
  3010 
  3026 
  3011 		if (ret >= 0) {
  3027 		if (ret >= 0) {
  3012 		    RETURN ( __mkSmallInteger(ret) );
  3028 		    RETURN ( __mkSmallInteger(ret) );
  3013 		}
  3029 		}
  3043 !
  3059 !
  3044 
  3060 
  3045 sync
  3061 sync
  3046     "make sure, that the OS writes cached data to the disk"
  3062     "make sure, that the OS writes cached data to the disk"
  3047 
  3063 
       
  3064     |error|
       
  3065 
  3048     self flush.
  3066     self flush.
  3049 
  3067 
  3050 %{
  3068 %{
  3051 #if !defined(__openVMS__)
  3069 #if !defined(__openVMS__)
  3052     FILEPOINTER f;
  3070     FILEPOINTER f;
  3068 	    }
  3086 	    }
  3069 #else
  3087 #else
  3070 
  3088 
  3071 	    __BEGIN_INTERRUPTABLE__
  3089 	    __BEGIN_INTERRUPTABLE__
  3072 	    do {
  3090 	    do {
  3073 		__threadErrno = 0;
       
  3074 		ret = fsync(fileno(f));
  3091 		ret = fsync(fileno(f));
  3075 	    } while ((ret < 0) && (__threadErrno == EINTR));
  3092 	    } while ((ret < 0) && (__threadErrno == EINTR));
  3076 	    __END_INTERRUPTABLE__
  3093 	    __END_INTERRUPTABLE__
  3077 
  3094 
  3078 	    if (ret >= 0) {
  3095 	    if (ret >= 0) {
  3079 		RETURN (self);
  3096 		RETURN (self);
  3080 	    }
  3097 	    }
  3081 #endif /* ! WIN32 */
  3098 #endif /* ! WIN32 */
  3082 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3099 	    error = __mkSmallInteger(__threadErrno);
  3083 	}
  3100 	}
  3084     }
  3101     }
  3085 #endif /* ! __openVMS__ */
  3102 #endif /* ! __openVMS__ */
  3086 %}.
  3103 %}.
  3087     lastErrorNumber notNil ifTrue:[^ self ioError].
  3104     error notNil ifTrue:[
  3088     handle isNil ifTrue:[^ self errorNotOpen].
  3105 	lastErrorNumber := error.
       
  3106 	self ioError:error.
       
  3107 	^ self.
       
  3108     ].
       
  3109     handle isNil ifTrue:[self errorNotOpen].
  3089 
  3110 
  3090     "
  3111     "
  3091 	|f|
  3112 	|f|
  3092 	f := 'x' asFilename writeStream.
  3113 	f := 'x' asFilename writeStream.
  3093 	f nextPutAll:'hallo'; sync; syncData; close
  3114 	f nextPutAll:'hallo'; sync; syncData; close
  3097 syncData
  3118 syncData
  3098     "make sure, that the OS writes cached data to the disk.
  3119     "make sure, that the OS writes cached data to the disk.
  3099      In this case, metadata is only written, if it is
  3120      In this case, metadata is only written, if it is
  3100      required to read the file's data (so metadata will not be written,
  3121      required to read the file's data (so metadata will not be written,
  3101      if only access/modification time has changed)."
  3122      if only access/modification time has changed)."
       
  3123 
       
  3124     |error|
  3102 
  3125 
  3103     self flush.
  3126     self flush.
  3104 
  3127 
  3105 %{
  3128 %{
  3106 #if defined(HAS_FDATASYNC)
  3129 #if defined(HAS_FDATASYNC)
  3124 	    }
  3147 	    }
  3125 #else
  3148 #else
  3126 
  3149 
  3127 	    __BEGIN_INTERRUPTABLE__
  3150 	    __BEGIN_INTERRUPTABLE__
  3128 	    do {
  3151 	    do {
  3129 		__threadErrno = 0;
       
  3130 		ret = fdatasync(fileno(f));
  3152 		ret = fdatasync(fileno(f));
  3131 	    } while ((ret < 0) && (__threadErrno == EINTR));
  3153 	    } while ((ret < 0) && (__threadErrno == EINTR));
  3132 	    __END_INTERRUPTABLE__
  3154 	    __END_INTERRUPTABLE__
  3133 
  3155 
  3134 	    if (ret >= 0) {
  3156 	    if (ret >= 0) {
  3135 		RETURN (self);
  3157 		RETURN (self);
  3136 	    }
  3158 	    }
  3137 #endif /* ! WIN32 */
  3159 #endif /* ! WIN32 */
  3138 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3160 	    error = __mkSmallInteger(__threadErrno);
  3139 	}
  3161 	}
  3140     }
  3162     }
  3141 #endif /* ! __openVMS__ */
  3163 #endif /* ! __openVMS__ */
  3142 %}.
  3164 %}.
  3143     lastErrorNumber notNil ifTrue:[^ self ioError].
  3165     error notNil ifTrue:[
       
  3166 	lastErrorNumber := error.
       
  3167 	self ioError:error.
       
  3168 	^ self.
       
  3169     ].
  3144     handle isNil ifTrue:[^ self errorNotOpen].
  3170     handle isNil ifTrue:[^ self errorNotOpen].
  3145 
  3171 
  3146     "if notdef HAS_DATASYNC, fall back"
  3172     "if notdef HAS_DATASYNC, fall back"
  3147     self sync.
  3173     self sync.
  3148 
  3174 
  3315 
  3341 
  3316      Use with care - non object oriented I/O.
  3342      Use with care - non object oriented I/O.
  3317      Warning: in general, you cannot use this method to pass data from other
  3343      Warning: in general, you cannot use this method to pass data from other
  3318      architectures since it does not care for byte order or float representation."
  3344      architectures since it does not care for byte order or float representation."
  3319 
  3345 
       
  3346     |error|
  3320 %{
  3347 %{
  3321     FILEPOINTER f;
  3348     FILEPOINTER f;
  3322     int cnt, offs, ret, _buffered;
  3349     int cnt, offs, ret, _buffered;
  3323     int objSize, nInstBytes;
  3350     int objSize, nInstBytes;
  3324     char *cp;
  3351     char *cp;
  3329     __INST(lastErrorNumber) = nil;
  3356     __INST(lastErrorNumber) = nil;
  3330     if ((__INST(handleType) == nil)
  3357     if ((__INST(handleType) == nil)
  3331      || (__INST(handleType) == @symbol(filePointer))
  3358      || (__INST(handleType) == @symbol(filePointer))
  3332      || (__INST(handleType) == @symbol(socketFilePointer))
  3359      || (__INST(handleType) == @symbol(socketFilePointer))
  3333      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3360      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3334         if (((fp = __INST(handle)) != nil)
  3361 	if (((fp = __INST(handle)) != nil)
  3335             && (__INST(mode) != @symbol(writeonly))
  3362 	    && (__INST(mode) != @symbol(writeonly))
  3336             && __bothSmallInteger(count, start)
  3363 	    && __bothSmallInteger(count, start)
  3337         ) {
  3364 	) {
  3338             f = __FILEVal(fp);
  3365 	    f = __FILEVal(fp);
  3339 
  3366 
  3340             cnt = __intVal(count);
  3367 	    cnt = __intVal(count);
  3341             offs = __intVal(start) - 1;
  3368 	    offs = __intVal(start) - 1;
  3342 
  3369 
  3343             if (__isExternalBytesLike(anObject)) {
  3370 	    if (__isExternalBytesLike(anObject)) {
  3344                 OBJ sz;
  3371 		OBJ sz;
  3345 
  3372 
  3346                 nInstBytes = 0;
  3373 		nInstBytes = 0;
  3347                 extPtr = (char *)(__externalBytesAddress(anObject));
  3374 		extPtr = (char *)(__externalBytesAddress(anObject));
  3348                 if (extPtr == NULL) goto bad;
  3375 		if (extPtr == NULL) goto bad;
  3349                 sz = __externalBytesSize(anObject);
  3376 		sz = __externalBytesSize(anObject);
  3350                 if (__isSmallInteger(sz)) {
  3377 		if (__isSmallInteger(sz)) {
  3351                     objSize = __intVal(sz);
  3378 		    objSize = __intVal(sz);
  3352                 } else {
  3379 		} else {
  3353                     objSize = 0; /* unknown */
  3380 		    objSize = 0; /* unknown */
  3354                 }
  3381 		}
  3355             } else {
  3382 	    } else {
  3356                 OBJ oClass = __Class(anObject);
  3383 		OBJ oClass = __Class(anObject);
  3357                 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3384 		int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3358 
  3385 
  3359                 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3386 		nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3360 
  3387 
  3361                 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3388 		switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3362                     case BYTEARRAY:
  3389 		    case BYTEARRAY:
  3363                     case WORDARRAY:
  3390 		    case WORDARRAY:
  3364                     case LONGARRAY:
  3391 		    case LONGARRAY:
  3365                     case SWORDARRAY:
  3392 		    case SWORDARRAY:
  3366                     case SLONGARRAY:
  3393 		    case SLONGARRAY:
  3367                     case FLOATARRAY:
  3394 		    case FLOATARRAY:
  3368                         break;
  3395 			break;
  3369                     case DOUBLEARRAY:
  3396 		    case DOUBLEARRAY:
  3370 #ifdef __NEED_DOUBLE_ALIGN
  3397 #ifdef __NEED_DOUBLE_ALIGN
  3371                         nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3398 			nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3372 #endif
  3399 #endif
  3373                         break;
  3400 			break;
  3374                     case LONGLONGARRAY:
  3401 		    case LONGLONGARRAY:
  3375                     case SLONGLONGARRAY:
  3402 		    case SLONGLONGARRAY:
  3376 #ifdef __NEED_LONGLONG_ALIGN
  3403 #ifdef __NEED_LONGLONG_ALIGN
  3377                         nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3404 			nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3378 #endif
  3405 #endif
  3379                         break;
  3406 			break;
  3380                     default:
  3407 		    default:
  3381                         goto bad;
  3408 			goto bad;
  3382                 }
  3409 		}
  3383                 extPtr = (char *)0;
  3410 		extPtr = (char *)0;
  3384                 objSize = __Size(anObject) - nInstBytes;
  3411 		objSize = __Size(anObject) - nInstBytes;
  3385             }
  3412 	    }
  3386 
  3413 
  3387             if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3414 	    if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3388                 _buffered = (__INST(buffered) == true);
  3415 		_buffered = (__INST(buffered) == true);
  3389                 if (_buffered) {
  3416 		if (_buffered) {
  3390                     __READING__(f);
  3417 		    __READING__(f);
  3391                 }
  3418 		}
  3392 
  3419 
  3393                 if (extPtr) {
  3420 		if (extPtr) {
  3394                     __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3421 		    __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3395                 } else {
  3422 		} else {
  3396                     /*
  3423 		    /*
  3397                      * on interrupt, anObject may be moved to another location.
  3424 		     * on interrupt, anObject may be moved to another location.
  3398                      * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__,
  3425 		     * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__,
  3399                      * to get a new address.
  3426 		     * to get a new address.
  3400                      */
  3427 		     */
  3401                     offs += nInstBytes;
  3428 		    offs += nInstBytes;
  3402                     __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3429 		    __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3403                 }
  3430 		}
  3404 #ifdef PRE_22_jan_2000
  3431 		/* 0 is NOT an EOF condition here ... */
  3405                 if (ret > 0)
  3432 		if (ret >= 0) {
  3406 #else
  3433 		    if (__isSmallInteger(__INST(position))) {
  3407                 /* 0 is NOT an EOF condition here ... */
  3434 			INT np = __intVal(__INST(position)) + ret;
  3408                 if (ret >= 0)
  3435 			OBJ t;
  3409 #endif
  3436 
  3410                 {
  3437 			t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3411                     if (__isSmallInteger(__INST(position))) {
  3438 		    } else {
  3412                         INT np = __intVal(__INST(position)) + ret;
  3439 			__INST(position) = nil; /* i.e. do not know */
  3413                         OBJ t;
  3440 		    }
  3414 
  3441 		    RETURN (__mkSmallInteger(ret));
  3415                         t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3442 		}
  3416                     } else {
  3443 		__INST(position) = nil;
  3417                         __INST(position) = nil; /* i.e. do not know */
  3444 		error = __mkSmallInteger(__threadErrno);
  3418                     }
  3445 	    }
  3419                     RETURN (__mkSmallInteger(ret));
  3446 	}
  3420                 }
       
  3421 #ifdef PRE_22_jan_2000
       
  3422                 if (ret == 0) {
       
  3423                     __INST(hitEOF) = true;
       
  3424                 } else /* ret < 0 */
       
  3425 #endif
       
  3426                 {
       
  3427                     __INST(position) = nil;
       
  3428                     __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
       
  3429                 }
       
  3430             }
       
  3431         }
       
  3432     }
  3447     }
  3433 bad: ;
  3448 bad: ;
  3434 %}.
  3449 %}.
  3435     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3450     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3436     lastErrorNumber notNil ifTrue:[^ self readError].
  3451     error notNil ifTrue:[
       
  3452 	lastErrorNumber := error.
       
  3453 	^ self readError:error
       
  3454     ].
  3437     handle isNil ifTrue:[^ self errorNotOpen].
  3455     handle isNil ifTrue:[^ self errorNotOpen].
  3438     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3456     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3439     "
  3457     "
  3440      count not integer or arg not bit-like (String, ByteArray etc)
  3458      count not integer or arg not bit-like (String, ByteArray etc)
  3441     "
  3459     "
  3445 nextByte
  3463 nextByte
  3446     "read the next byte and return it as an Integer; return nil on error.
  3464     "read the next byte and return it as an Integer; return nil on error.
  3447      This is allowed in both text and binary modes, always returning the
  3465      This is allowed in both text and binary modes, always returning the
  3448      bytes binary value as an integer in 0..255."
  3466      bytes binary value as an integer in 0..255."
  3449 
  3467 
       
  3468     |error|
  3450 %{
  3469 %{
  3451     FILEPOINTER f;
  3470     FILEPOINTER f;
  3452     unsigned char byte;
  3471     unsigned char byte;
  3453     int ret, _buffered;
  3472     int ret, _buffered;
  3454     OBJ fp;
  3473     OBJ fp;
  3481 
  3500 
  3482 	    if (ret == 0) {
  3501 	    if (ret == 0) {
  3483 		__INST(hitEOF) = true;
  3502 		__INST(hitEOF) = true;
  3484 	    } else /* ret < 0 */ {
  3503 	    } else /* ret < 0 */ {
  3485 		__INST(position) = nil;
  3504 		__INST(position) = nil;
  3486 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3505 		error = __mkSmallInteger(__threadErrno);
  3487 	    }
  3506 	    }
  3488 	}
  3507 	}
  3489     }
  3508     }
  3490 %}.
  3509 %}.
  3491     hitEOF ifTrue:[^ self pastEndRead].
  3510     hitEOF ifTrue:[^ self pastEndRead].
  3492     lastErrorNumber notNil ifTrue:[^ self readError].
  3511     error notNil ifTrue:[
       
  3512 	lastErrorNumber := error.
       
  3513 	^ self readError:error
       
  3514     ].
  3493     handle isNil ifTrue:[^ self errorNotOpen].
  3515     handle isNil ifTrue:[^ self errorNotOpen].
  3494     ^ self errorWriteOnly
  3516     ^ self errorWriteOnly
  3495 !
  3517 !
  3496 
  3518 
  3497 nextBytes:count into:anObject startingAt:start
  3519 nextBytes:count into:anObject startingAt:start
  3517      Use with care - non object oriented I/O.
  3539      Use with care - non object oriented I/O.
  3518      Warning: in general, you cannot use this method to pass data from other
  3540      Warning: in general, you cannot use this method to pass data from other
  3519      architectures (unless you prepared the buffer with care),
  3541      architectures (unless you prepared the buffer with care),
  3520      since it does not care for byte order or float representation."
  3542      since it does not care for byte order or float representation."
  3521 
  3543 
       
  3544     |error|
  3522 %{
  3545 %{
  3523     FILEPOINTER f;
  3546     FILEPOINTER f;
  3524     int cnt, offs, ret, _buffered;
  3547     int cnt, offs, ret, _buffered;
  3525     int objSize, nInstBytes;
  3548     int objSize, nInstBytes;
  3526     char *extPtr;
  3549     char *extPtr;
  3529     __INST(lastErrorNumber) = nil;
  3552     __INST(lastErrorNumber) = nil;
  3530     if ((__INST(handleType) == nil)
  3553     if ((__INST(handleType) == nil)
  3531      || (__INST(handleType) == @symbol(filePointer))
  3554      || (__INST(handleType) == @symbol(filePointer))
  3532      || (__INST(handleType) == @symbol(socketFilePointer))
  3555      || (__INST(handleType) == @symbol(socketFilePointer))
  3533      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3556      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3534         if (((fp = __INST(handle)) != nil)
  3557 	if (((fp = __INST(handle)) != nil)
  3535             && (__INST(mode) != @symbol(writeonly))
  3558 	    && (__INST(mode) != @symbol(writeonly))
  3536             && __bothSmallInteger(count, start)
  3559 	    && __bothSmallInteger(count, start)
  3537         ) {
  3560 	) {
  3538             f = __FILEVal(fp);
  3561 	    f = __FILEVal(fp);
  3539 
  3562 
  3540             cnt = __intVal(count);
  3563 	    cnt = __intVal(count);
  3541             offs = __intVal(start) - 1;
  3564 	    offs = __intVal(start) - 1;
  3542 
  3565 
  3543             if (__isExternalBytesLike(anObject)) {
  3566 	    if (__isExternalBytesLike(anObject)) {
  3544                 OBJ sz;
  3567 		OBJ sz;
  3545 
  3568 
  3546                 nInstBytes = 0;
  3569 		nInstBytes = 0;
  3547                 extPtr = (char *)(__externalBytesAddress(anObject));
  3570 		extPtr = (char *)(__externalBytesAddress(anObject));
  3548                 if (extPtr == NULL) goto bad;
  3571 		if (extPtr == NULL) goto bad;
  3549                 sz = __externalBytesSize(anObject);
  3572 		sz = __externalBytesSize(anObject);
  3550                 if (__isSmallInteger(sz)) {
  3573 		if (__isSmallInteger(sz)) {
  3551                     objSize = __intVal(sz);
  3574 		    objSize = __intVal(sz);
  3552                 } else {
  3575 		} else {
  3553                     objSize = 0; /* unknown */
  3576 		    objSize = 0; /* unknown */
  3554                 }
  3577 		}
  3555             } else {
  3578 	    } else {
  3556                 OBJ oClass = __Class(anObject);
  3579 		OBJ oClass = __Class(anObject);
  3557                 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3580 		int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3558 
  3581 
  3559                 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3582 		nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3560                 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3583 		switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3561                     case BYTEARRAY:
  3584 		    case BYTEARRAY:
  3562                     case WORDARRAY:
  3585 		    case WORDARRAY:
  3563                     case LONGARRAY:
  3586 		    case LONGARRAY:
  3564                     case SWORDARRAY:
  3587 		    case SWORDARRAY:
  3565                     case SLONGARRAY:
  3588 		    case SLONGARRAY:
  3566                     case FLOATARRAY:
  3589 		    case FLOATARRAY:
  3567                         break;
  3590 			break;
  3568                     case DOUBLEARRAY:
  3591 		    case DOUBLEARRAY:
  3569 #ifdef __NEED_DOUBLE_ALIGN
  3592 #ifdef __NEED_DOUBLE_ALIGN
  3570                         nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3593 			nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3571 #endif
  3594 #endif
  3572                         break;
  3595 			break;
  3573                     case LONGLONGARRAY:
  3596 		    case LONGLONGARRAY:
  3574                     case SLONGLONGARRAY:
  3597 		    case SLONGLONGARRAY:
  3575 #ifdef __NEED_LONGLONG_ALIGN
  3598 #ifdef __NEED_LONGLONG_ALIGN
  3576                         nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3599 			nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3577 #endif
  3600 #endif
  3578                         break;
  3601 			break;
  3579                     default:
  3602 		    default:
  3580                         goto bad;
  3603 			goto bad;
  3581                 }
  3604 		}
  3582                 extPtr = (char *)0;
  3605 		extPtr = (char *)0;
  3583                 objSize = __Size(anObject) - nInstBytes;
  3606 		objSize = __Size(anObject) - nInstBytes;
  3584             }
  3607 	    }
  3585             if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3608 	    if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3586                 _buffered = (__INST(buffered) == true);
  3609 		_buffered = (__INST(buffered) == true);
  3587                 if (_buffered) {
  3610 		if (_buffered) {
  3588                     __READING__(f);
  3611 		    __READING__(f);
  3589                 }
  3612 		}
  3590 
  3613 
  3591                 if (extPtr) {
  3614 		if (extPtr) {
  3592                     __READBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3615 		    __READBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3593                 } else {
  3616 		} else {
  3594                     /*
  3617 		    /*
  3595                      * on interrupt, anObject may be moved to another location.
  3618 		     * on interrupt, anObject may be moved to another location.
  3596                      * So we pass anObject, and the offset to the __READBYTES_OBJ__ macro.
  3619 		     * So we pass anObject, and the offset to the __READBYTES_OBJ__ macro.
  3597                      */
  3620 		     */
  3598                     offs += nInstBytes;
  3621 		    offs += nInstBytes;
  3599                     __READBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3622 		    __READBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3600                 }
  3623 		}
  3601 
  3624 
  3602                 if (ret > 0) {
  3625 		if (ret > 0) {
  3603                     if (__isSmallInteger(__INST(position))) {
  3626 		    if (__isSmallInteger(__INST(position))) {
  3604                         INT np = __intVal(__INST(position)) + ret;
  3627 			INT np = __intVal(__INST(position)) + ret;
  3605                         OBJ t;
  3628 			OBJ t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3606 
  3629 		    } else {
  3607                         t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3630 			__INST(position) = nil; /* i.e. do not know */
  3608                     } else {
  3631 		    }
  3609                         __INST(position) = nil; /* i.e. do not know */
  3632 		    RETURN (__mkSmallInteger(ret));
  3610                     }
  3633 		}
  3611                     RETURN (__mkSmallInteger(ret));
  3634 		if (ret == 0) {
  3612                 }
  3635 		    __INST(hitEOF) = true;
  3613                 if (ret == 0) {
  3636 		} else /* ret < 0 */ {
  3614                     __INST(hitEOF) = true;
  3637 		    __INST(position) = nil;
  3615                 } else /* ret < 0 */ {
  3638 		    error = __mkSmallInteger(__threadErrno);
  3616                     __INST(position) = nil;
  3639 		}
  3617                     __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3640 	    }
  3618                 }
  3641 	}
  3619             }
       
  3620         }
       
  3621     }
  3642     }
  3622 bad: ;
  3643 bad: ;
  3623 %}.
  3644 %}.
  3624     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3645     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3625     lastErrorNumber notNil ifTrue:[^ self readError].
  3646     error notNil ifTrue:[
       
  3647 	lastErrorNumber := error.
       
  3648 	^ self readError:error
       
  3649     ].
  3626     handle isNil ifTrue:[^ self errorNotOpen].
  3650     handle isNil ifTrue:[^ self errorNotOpen].
  3627     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3651     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3628     "
  3652     "
  3629      count not integer or arg not bit-like (String, ByteArray etc)
  3653      count not integer or arg not bit-like (String, ByteArray etc)
  3630     "
  3654     "
  3645      If msbFlag is true, value is read with most-significant byte first,
  3669      If msbFlag is true, value is read with most-significant byte first,
  3646      otherwise least-significant byte comes first.
  3670      otherwise least-significant byte comes first.
  3647      A nil is returned, if EOF is hit before all 4 bytes have been read.
  3671      A nil is returned, if EOF is hit before all 4 bytes have been read.
  3648      Works in both binary and text modes."
  3672      Works in both binary and text modes."
  3649 
  3673 
       
  3674     |error|
  3650 %{
  3675 %{
  3651     OBJ fp;
  3676     OBJ fp;
  3652 
  3677 
  3653     __INST(lastErrorNumber) = nil;
  3678     __INST(lastErrorNumber) = nil;
  3654     if ((__INST(handleType) == nil)
  3679     if ((__INST(handleType) == nil)
  3711 #endif
  3736 #endif
  3712 	    }
  3737 	    }
  3713 
  3738 
  3714 	    if (ret < 0) {
  3739 	    if (ret < 0) {
  3715 		__INST(position) = nil;
  3740 		__INST(position) = nil;
  3716 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3741 		error = __mkSmallInteger(__threadErrno);
  3717 	    } else /* ret == 0 */ {
  3742 	    } else /* ret == 0 */ {
  3718 		__INST(hitEOF) = true;
  3743 		__INST(hitEOF) = true;
  3719 	    }
  3744 	    }
  3720 	}
  3745 	}
  3721     }
  3746     }
  3722 %}.
  3747 %}.
  3723     hitEOF ifTrue:[^ self pastEndRead].
  3748     hitEOF ifTrue:[^ self pastEndRead].
  3724     handle isNil ifTrue:[^ self errorNotOpen].
  3749     handle isNil ifTrue:[^ self errorNotOpen].
  3725     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3750     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3726     ^ self readError.
  3751     lastErrorNumber := error.
       
  3752     ^ self readError:error.
  3727 !
  3753 !
  3728 
  3754 
  3729 nextShortMSB:msbFlag
  3755 nextShortMSB:msbFlag
  3730     "Read two bytes and return the value as a 16-bit signed Integer.
  3756     "Read two bytes and return the value as a 16-bit signed Integer.
  3731      If msbFlag is true, value is read with most-significant byte first,
  3757      If msbFlag is true, value is read with most-significant byte first,
  3732      otherwise least-significant byte comes first.
  3758      otherwise least-significant byte comes first.
  3733      A nil is returned if EOF is reached (also when EOF is hit after the first byte).
  3759      A nil is returned if EOF is reached (also when EOF is hit after the first byte).
  3734      Works in both binary and text modes."
  3760      Works in both binary and text modes."
  3735 
  3761 
       
  3762     |error|
  3736 %{
  3763 %{
  3737     OBJ fp;
  3764     OBJ fp;
  3738 
  3765 
  3739     __INST(lastErrorNumber) = nil;
  3766     __INST(lastErrorNumber) = nil;
  3740     if ((__INST(handleType) == nil)
  3767     if ((__INST(handleType) == nil)
  3784 		RETURN (__mkSmallInteger(value));
  3811 		RETURN (__mkSmallInteger(value));
  3785 	    }
  3812 	    }
  3786 
  3813 
  3787 	    if (ret < 0) {
  3814 	    if (ret < 0) {
  3788 		__INST(position) = nil; /* i.e. do not know */
  3815 		__INST(position) = nil; /* i.e. do not know */
  3789 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3816 		error = __mkSmallInteger(__threadErrno);
  3790 	    } else /* ret == 0 */ {
  3817 	    } else /* ret == 0 */ {
  3791 		__INST(hitEOF) = true;
  3818 		__INST(hitEOF) = true;
  3792 	    }
  3819 	    }
  3793 	}
  3820 	}
  3794     }
  3821     }
  3795 %}.
  3822 %}.
  3796     hitEOF ifTrue:[^ self pastEndRead].
  3823     hitEOF ifTrue:[^ self pastEndRead].
  3797     handle isNil ifTrue:[^ self errorNotOpen].
  3824     handle isNil ifTrue:[^ self errorNotOpen].
  3798     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3825     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3799     ^ self readError.
  3826     lastErrorNumber := error.
       
  3827     ^ self readError:error.
  3800 !
  3828 !
  3801 
  3829 
  3802 nextUnsignedLongMSB:msbFlag
  3830 nextUnsignedLongMSB:msbFlag
  3803     "Read four bytes and return the value as a 32-bit unsigned Integer, which may be
  3831     "Read four bytes and return the value as a 32-bit unsigned Integer, which may be
  3804      a LargeInteger.
  3832      a LargeInteger.
  3805      If msbFlag is true, value is read with most-significant byte first, otherwise
  3833      If msbFlag is true, value is read with most-significant byte first, otherwise
  3806      least-significant byte comes first.
  3834      least-significant byte comes first.
  3807      A nil is returned, if endOfFile occurs before all 4 bytes have been read.
  3835      A nil is returned, if endOfFile occurs before all 4 bytes have been read.
  3808      Works in both binary and text modes."
  3836      Works in both binary and text modes."
  3809 
  3837 
       
  3838     |error|
  3810 %{
  3839 %{
  3811     OBJ fp;
  3840     OBJ fp;
  3812 
  3841 
  3813     __INST(lastErrorNumber) = nil;
  3842     __INST(lastErrorNumber) = nil;
  3814     if ((__INST(handleType) == nil)
  3843     if ((__INST(handleType) == nil)
  3872 #endif
  3901 #endif
  3873 	    }
  3902 	    }
  3874 
  3903 
  3875 	    if (ret < 0) {
  3904 	    if (ret < 0) {
  3876 		__INST(position) = nil; /* i.e. do not know */
  3905 		__INST(position) = nil; /* i.e. do not know */
  3877 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3906 		error = __mkSmallInteger(__threadErrno);
  3878 	    } else /* ret == 0 */ {
  3907 	    } else /* ret == 0 */ {
  3879 		__INST(hitEOF) = true;
  3908 		__INST(hitEOF) = true;
  3880 	    }
  3909 	    }
  3881 	}
  3910 	}
  3882     }
  3911     }
  3883 %}.
  3912 %}.
  3884     hitEOF ifTrue:[^ self pastEndRead].
  3913     hitEOF ifTrue:[^ self pastEndRead].
  3885     handle isNil ifTrue:[^ self errorNotOpen].
  3914     handle isNil ifTrue:[^ self errorNotOpen].
  3886     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3915     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3887     ^ self readError.
  3916     lastErrorNumber := error.
       
  3917     ^ self readError:error.
  3888 !
  3918 !
  3889 
  3919 
  3890 nextUnsignedShortMSB:msbFlag
  3920 nextUnsignedShortMSB:msbFlag
  3891     "Read two bytes and return the value as a 16-bit unsigned Integer.
  3921     "Read two bytes and return the value as a 16-bit unsigned Integer.
  3892      If msbFlag is true, value is read with most-significant byte first,
  3922      If msbFlag is true, value is read with most-significant byte first,
  3893      otherwise least-significant byte comes first.
  3923      otherwise least-significant byte comes first.
  3894      A nil is returned if EOF is reached (also when EOF is hit after the first byte).
  3924      A nil is returned if EOF is reached (also when EOF is hit after the first byte).
  3895      Works in both binary and text modes."
  3925      Works in both binary and text modes."
  3896 
  3926 
       
  3927     |error|
  3897 %{
  3928 %{
  3898     OBJ fp;
  3929     OBJ fp;
  3899 
  3930 
  3900     __INST(lastErrorNumber) = nil;
  3931     __INST(lastErrorNumber) = nil;
  3901     if ((__INST(handleType) == nil)
  3932     if ((__INST(handleType) == nil)
  3945 		RETURN (__mkSmallInteger(value));
  3976 		RETURN (__mkSmallInteger(value));
  3946 	    }
  3977 	    }
  3947 
  3978 
  3948 	    if (ret < 0) {
  3979 	    if (ret < 0) {
  3949 		__INST(position) = nil; /* i.e. do not know */
  3980 		__INST(position) = nil; /* i.e. do not know */
  3950 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  3981 		error = __mkSmallInteger(__threadErrno);
  3951 	    } else /* ret == 0 */ {
  3982 	    } else /* ret == 0 */ {
  3952 		__INST(hitEOF) = true;
  3983 		__INST(hitEOF) = true;
  3953 	    }
  3984 	    }
  3954 	}
  3985 	}
  3955     }
  3986     }
  3956 %}.
  3987 %}.
  3957     hitEOF ifTrue:[^ self pastEndRead].
  3988     hitEOF ifTrue:[^ self pastEndRead].
  3958     handle isNil ifTrue:[^ self errorNotOpen].
  3989     handle isNil ifTrue:[^ self errorNotOpen].
  3959     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3990     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3960     ^ self readError.
  3991     lastErrorNumber := error.
       
  3992     ^ self readError:error.
  3961 !
  3993 !
  3962 
  3994 
  3963 nextWord
  3995 nextWord
  3964     <resource: #obsolete>
  3996     <resource: #obsolete>
  3965     "in text-mode:
  3997     "in text-mode:
  3980 
  4012 
  3981 nextPutByte:aByteValue
  4013 nextPutByte:aByteValue
  3982     "write a byte.
  4014     "write a byte.
  3983      Works in both binary and text modes."
  4015      Works in both binary and text modes."
  3984 
  4016 
       
  4017 |error|
       
  4018 
  3985 %{
  4019 %{
  3986     FILEPOINTER f;
  4020     FILEPOINTER f;
  3987     char c;
  4021     char c;
  3988     OBJ fp;
  4022     OBJ fp;
  3989     int cnt, _buffered;
  4023     int cnt, _buffered;
  4023 		RETURN (self);
  4057 		RETURN (self);
  4024 	    }
  4058 	    }
  4025 	    if (cnt < 0) {
  4059 	    if (cnt < 0) {
  4026 		__INST(position) = nil; /* i.e. do not know */
  4060 		__INST(position) = nil; /* i.e. do not know */
  4027 	    }
  4061 	    }
  4028 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4062 	    error = __mkSmallInteger(__threadErrno);
  4029 	}
  4063 	}
  4030     }
  4064     }
  4031 %}.
  4065 %}.
  4032     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4066     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4033     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4067     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4034     self writeError.
  4068     lastErrorNumber := error.
       
  4069     self writeError:error.
  4035 !
  4070 !
  4036 
  4071 
  4037 nextPutBytes:count from:anObject startingAt:start
  4072 nextPutBytes:count from:anObject startingAt:start
  4038     "write count bytes from an object starting at index start.
  4073     "write count bytes from an object starting at index start.
  4039      return the number of bytes written - which could be 0.
  4074      return the number of bytes written - which could be 0.
  4041      (i.e. be a ByteArray, String, Float- or DoubleArray),
  4076      (i.e. be a ByteArray, String, Float- or DoubleArray),
  4042      or an externalBytes object (with known size).
  4077      or an externalBytes object (with known size).
  4043 
  4078 
  4044      Use with care - non object oriented i/o.
  4079      Use with care - non object oriented i/o.
  4045      Warning:
  4080      Warning:
  4046         in general, you cannot use this method to pass non-byte data to other
  4081 	in general, you cannot use this method to pass non-byte data to other
  4047         architectures (unless you prepared the buffer with care),
  4082 	architectures (unless you prepared the buffer with care),
  4048         since it does not care for byte order or float representation."
  4083 	since it does not care for byte order or float representation."
       
  4084 
       
  4085     |error|
  4049 
  4086 
  4050 %{
  4087 %{
  4051     FILEPOINTER f;
  4088     FILEPOINTER f;
  4052     int cnt, len, offs, ret;
  4089     int cnt, len, offs, ret;
  4053     int objSize, nInstBytes, _buffered;
  4090     int objSize, nInstBytes, _buffered;
  4057     __INST(lastErrorNumber) = nil;
  4094     __INST(lastErrorNumber) = nil;
  4058     if ((__INST(handleType) == nil)
  4095     if ((__INST(handleType) == nil)
  4059      || (__INST(handleType) == @symbol(filePointer))
  4096      || (__INST(handleType) == @symbol(filePointer))
  4060      || (__INST(handleType) == @symbol(socketFilePointer))
  4097      || (__INST(handleType) == @symbol(socketFilePointer))
  4061      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4098      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4062         if (((fp = __INST(handle)) != nil)
  4099 	if (((fp = __INST(handle)) != nil)
  4063             && (__INST(mode) != @symbol(readonly))
  4100 	    && (__INST(mode) != @symbol(readonly))
  4064             && __bothSmallInteger(count, start)
  4101 	    && __bothSmallInteger(count, start)
  4065         ) {
  4102 	) {
  4066             len = __intVal(count);
  4103 	    len = __intVal(count);
  4067             offs = __intVal(start) - 1;
  4104 	    offs = __intVal(start) - 1;
  4068             f = __FILEVal(fp);
  4105 	    f = __FILEVal(fp);
  4069 
  4106 
  4070             if (__isExternalBytesLike(anObject)) {
  4107 	    if (__isExternalBytesLike(anObject)) {
  4071                 OBJ sz;
  4108 		OBJ sz;
  4072 
  4109 
  4073                 nInstBytes = 0;
  4110 		nInstBytes = 0;
  4074                 extPtr = (char *)__externalBytesAddress(anObject);
  4111 		extPtr = (char *)__externalBytesAddress(anObject);
  4075                 if (extPtr == NULL) goto bad;
  4112 		if (extPtr == NULL) goto bad;
  4076                 sz = __externalBytesSize(anObject);
  4113 		sz = __externalBytesSize(anObject);
  4077                 if (__isSmallInteger(sz)) {
  4114 		if (__isSmallInteger(sz)) {
  4078                     objSize = __intVal(sz);
  4115 		    objSize = __intVal(sz);
  4079                 } else {
  4116 		} else {
  4080                     objSize = 0; /* unknown */
  4117 		    objSize = 0; /* unknown */
  4081                 }
  4118 		}
  4082             } else {
  4119 	    } else {
  4083                 OBJ oClass = __Class(anObject);
  4120 		OBJ oClass = __Class(anObject);
  4084                 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  4121 		int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  4085 
  4122 
  4086                 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  4123 		nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  4087                 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  4124 		switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  4088                     case BYTEARRAY:
  4125 		    case BYTEARRAY:
  4089                     case WORDARRAY:
  4126 		    case WORDARRAY:
  4090                     case LONGARRAY:
  4127 		    case LONGARRAY:
  4091                     case SWORDARRAY:
  4128 		    case SWORDARRAY:
  4092                     case SLONGARRAY:
  4129 		    case SLONGARRAY:
  4093                     case FLOATARRAY:
  4130 		    case FLOATARRAY:
  4094                         break;
  4131 			break;
  4095                     case DOUBLEARRAY:
  4132 		    case DOUBLEARRAY:
  4096 #ifdef __NEED_DOUBLE_ALIGN
  4133 #ifdef __NEED_DOUBLE_ALIGN
  4097                         nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  4134 			nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  4098 #endif
  4135 #endif
  4099                         break;
  4136 			break;
  4100                     case LONGLONGARRAY:
  4137 		    case LONGLONGARRAY:
  4101                     case SLONGLONGARRAY:
  4138 		    case SLONGLONGARRAY:
  4102 #ifdef __NEED_LONGLONG_ALIGN
  4139 #ifdef __NEED_LONGLONG_ALIGN
  4103                         nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  4140 			nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  4104 #endif
  4141 #endif
  4105                         break;
  4142 			break;
  4106                     default:
  4143 		    default:
  4107                         goto bad;
  4144 			goto bad;
  4108                 }
  4145 		}
  4109                 extPtr = (char *)0;
  4146 		extPtr = (char *)0;
  4110                 objSize = __Size(anObject) - nInstBytes;
  4147 		objSize = __Size(anObject) - nInstBytes;
  4111             }
  4148 	    }
  4112             if ( (offs >= 0) && (len >= 0) && (objSize >= (len + offs)) ) {
  4149 	    if ( (offs >= 0) && (len >= 0) && (objSize >= (len + offs)) ) {
  4113                 if (_buffered = (__INST(buffered) == true)) {
  4150 		if (_buffered = (__INST(buffered) == true)) {
  4114                     __WRITING__(f)
  4151 		    __WRITING__(f)
  4115                 }
  4152 		}
  4116 
  4153 
  4117                 if (extPtr) {
  4154 		if (extPtr) {
  4118                     __WRITEBYTES__(cnt, f, extPtr+offs, len, _buffered, __INST(handleType));
  4155 		    __WRITEBYTES__(cnt, f, extPtr+offs, len, _buffered, __INST(handleType));
  4119                 } else {
  4156 		} else {
  4120                     /*
  4157 		    /*
  4121                      * on interrupt, anObject may be moved to another location.
  4158 		     * on interrupt, anObject may be moved to another location.
  4122                      * So we pass anObject, and the offset to the __WRITEBYTES_OBJ__ macro.
  4159 		     * So we pass anObject, and the offset to the __WRITEBYTES_OBJ__ macro.
  4123                      */
  4160 		     */
  4124                     offs += nInstBytes;
  4161 		    offs += nInstBytes;
  4125                     __WRITEBYTES_OBJ__(cnt, f, anObject, offs, len, _buffered, __INST(handleType));
  4162 		    __WRITEBYTES_OBJ__(cnt, f, anObject, offs, len, _buffered, __INST(handleType));
  4126                 }
  4163 		}
  4127 
  4164 
  4128                 if (cnt >= 0) {
  4165 		if (cnt >= 0) {
  4129                     if (__isSmallInteger(__INST(position))) {
  4166 		    if (__isSmallInteger(__INST(position))) {
  4130                         INT np = __intVal(__INST(position)) + cnt;
  4167 			INT np = __intVal(__INST(position)) + cnt;
  4131                         OBJ t;
  4168 			OBJ t;
  4132 
  4169 
  4133                         t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4170 			t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4134                     } else {
  4171 		    } else {
  4135                         __INST(position) = nil; /* i.e. do not know */
  4172 			__INST(position) = nil; /* i.e. do not know */
  4136                     }
  4173 		    }
  4137                     RETURN ( __mkSmallInteger(cnt) );
  4174 		    RETURN ( __mkSmallInteger(cnt) );
  4138                 } else /* cnt < 0 */ {
  4175 		} else /* cnt < 0 */ {
  4139                     if (
  4176 		    if (
  4140 #ifdef EWOULDBLOCK
  4177 #ifdef EWOULDBLOCK
  4141                         (__threadErrno == EWOULDBLOCK) ||
  4178 			(__threadErrno == EWOULDBLOCK) ||
  4142 #endif
  4179 #endif
  4143                         (__threadErrno == EAGAIN)
  4180 			(__threadErrno == EAGAIN)
  4144                     ) {
  4181 		    ) {
  4145                         RETURN ( __mkSmallInteger(0) );
  4182 			RETURN ( __mkSmallInteger(0) );
  4146                     }
  4183 		    }
  4147                     __INST(position) = nil; /* i.e. do not know */
  4184 		    __INST(position) = nil; /* i.e. do not know */
  4148                     __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4185 		    error = __mkSmallInteger(__threadErrno);
  4149                 }
  4186 		}
  4150             }
  4187 	    }
  4151         }
  4188 	}
  4152     }
  4189     }
  4153 bad: ;
  4190 bad: ;
  4154 %}.
  4191 %}.
  4155     lastErrorNumber notNil ifTrue:[^ self writeError].
  4192     error notNil ifTrue:[
       
  4193 	lastErrorNumber := error.
       
  4194 	self writeError:error.
       
  4195 	^ self
       
  4196     ].
  4156     handle isNil ifTrue:[^ self errorNotOpen].
  4197     handle isNil ifTrue:[^ self errorNotOpen].
  4157     (mode == #readonly) ifTrue:[^ self errorReadOnly].
  4198     (mode == #readonly) ifTrue:[^ self errorReadOnly].
  4158     ^ self primitiveFailed
  4199     ^ self primitiveFailed
  4159 !
  4200 !
  4160 
  4201 
  4161 nextPutLong:aNumber MSB:msbFlag
  4202 nextPutLong:aNumber MSB:msbFlag
  4162     "Write the argument, aNumber as a long (four bytes). If msbFlag is
  4203     "Write the argument, aNumber as a long (four bytes). If msbFlag is
  4163      true, data is written most-significant byte first; otherwise least
  4204      true, data is written most-significant byte first; otherwise least
  4164      first.
  4205      first.
  4165      Works in both binary and text modes."
  4206      Works in both binary and text modes."
       
  4207 
       
  4208     |error|
  4166 
  4209 
  4167 %{
  4210 %{
  4168     int num;
  4211     int num;
  4169     union {
  4212     union {
  4170 	char bytes[4];
  4213 	char bytes[4];
  4237 		    __INST(position) = nil; /* i.e. do not know */
  4280 		    __INST(position) = nil; /* i.e. do not know */
  4238 		}
  4281 		}
  4239 		RETURN ( self );
  4282 		RETURN ( self );
  4240 	    }
  4283 	    }
  4241 	    __INST(position) = nil; /* i.e. do not know */
  4284 	    __INST(position) = nil; /* i.e. do not know */
  4242 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4285 	    error = __mkSmallInteger(__threadErrno);
  4243 	}
  4286 	}
  4244     }
  4287     }
  4245 badArg: ;
  4288 badArg: ;
  4246 %}.
  4289 %}.
  4247     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4290     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4248     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4291     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4249     lastErrorNumber notNil ifTrue:[self writeError. ^ self].
  4292     error notNil ifTrue:[
       
  4293 	lastErrorNumber := error.
       
  4294 	self writeError:error.
       
  4295 	^ self
       
  4296     ].
  4250 
  4297 
  4251     aNumber isInteger ifTrue:[
  4298     aNumber isInteger ifTrue:[
  4252 	^ super nextPutLong:aNumber MSB:msbFlag
  4299 	^ super nextPutLong:aNumber MSB:msbFlag
  4253     ].
  4300     ].
  4254     self argumentMustBeInteger
  4301     self argumentMustBeInteger
  4258     "Write the argument, anIntegerOrCharacter as a short (two bytes). If msbFlag is
  4305     "Write the argument, anIntegerOrCharacter as a short (two bytes). If msbFlag is
  4259      true, data is written most-significant byte first; otherwise least
  4306      true, data is written most-significant byte first; otherwise least
  4260      first.
  4307      first.
  4261      Works in both binary and text modes."
  4308      Works in both binary and text modes."
  4262 
  4309 
       
  4310     |error|
  4263 %{
  4311 %{
  4264     int num;
  4312     int num;
  4265     union {
  4313     union {
  4266         char bytes[2];
  4314 	char bytes[2];
  4267         short shortVal;
  4315 	short shortVal;
  4268     } u;
  4316     } u;
  4269 
  4317 
  4270     FILEPOINTER f;
  4318     FILEPOINTER f;
  4271     int cnt, _buffered;
  4319     int cnt, _buffered;
  4272     OBJ fp;
  4320     OBJ fp;
  4274     __INST(lastErrorNumber) = nil;
  4322     __INST(lastErrorNumber) = nil;
  4275     if ((__INST(handleType) == nil)
  4323     if ((__INST(handleType) == nil)
  4276      || (__INST(handleType) == @symbol(filePointer))
  4324      || (__INST(handleType) == @symbol(filePointer))
  4277      || (__INST(handleType) == @symbol(socketFilePointer))
  4325      || (__INST(handleType) == @symbol(socketFilePointer))
  4278      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4326      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4279         if (((fp = __INST(handle)) != nil)
  4327 	if (((fp = __INST(handle)) != nil)
  4280             && (__INST(mode) != @symbol(readonly))
  4328 	    && (__INST(mode) != @symbol(readonly))
  4281         ) {
  4329 	) {
  4282             if (__isSmallInteger(anIntegerOrCharacter)) {
  4330 	    if (__isSmallInteger(anIntegerOrCharacter)) {
  4283                 num = __intVal(anIntegerOrCharacter);
  4331 		num = __intVal(anIntegerOrCharacter);
  4284             } else if (__isCharacter(anIntegerOrCharacter)) {
  4332 	    } else if (__isCharacter(anIntegerOrCharacter)) {
  4285                 num = __smallIntegerVal(__characterVal(anIntegerOrCharacter));
  4333 		num = __smallIntegerVal(__characterVal(anIntegerOrCharacter));
  4286             } else
  4334 	    } else
  4287                 goto out;
  4335 		goto out;
  4288 
  4336 
  4289             if (msbFlag == true) {
  4337 	    if (msbFlag == true) {
  4290 #if defined(__MSBFIRST__)
  4338 #if defined(__MSBFIRST__)
  4291                 u.shortVal = num;
  4339 		u.shortVal = num;
  4292 #else
  4340 #else
  4293                 u.bytes[0] = (num >> 8) & 0xFF;
  4341 		u.bytes[0] = (num >> 8) & 0xFF;
  4294                 u.bytes[1] = num & 0xFF;
  4342 		u.bytes[1] = num & 0xFF;
  4295 #endif
  4343 #endif
  4296             } else {
  4344 	    } else {
  4297 #if defined(__LSBFIRST__)
  4345 #if defined(__LSBFIRST__)
  4298                 u.shortVal = num;
  4346 		u.shortVal = num;
  4299 #else
  4347 #else
  4300                 u.bytes[1] = (num >> 8) & 0xFF;
  4348 		u.bytes[1] = (num >> 8) & 0xFF;
  4301                 u.bytes[0] = num & 0xFF;
  4349 		u.bytes[0] = num & 0xFF;
  4302 #endif
  4350 #endif
  4303             }
  4351 	    }
  4304 
  4352 
  4305             f = __FILEVal(fp);
  4353 	    f = __FILEVal(fp);
  4306             if (_buffered = (__INST(buffered) == true)) {
  4354 	    if (_buffered = (__INST(buffered) == true)) {
  4307                 __WRITING__(f)
  4355 		__WRITING__(f)
  4308             }
  4356 	    }
  4309             __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType));
  4357 	    __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType));
  4310 
  4358 
  4311             if (cnt == 2) {
  4359 	    if (cnt == 2) {
  4312                 if (__isSmallInteger(__INST(position))) {
  4360 		if (__isSmallInteger(__INST(position))) {
  4313                     INT np = __intVal(__INST(position)) + 2;
  4361 		    INT np = __intVal(__INST(position)) + 2;
  4314                     OBJ t;
  4362 		    OBJ t;
  4315 
  4363 
  4316                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4364 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4317                 } else {
  4365 		} else {
  4318                     __INST(position) = nil; /* i.e. do not know */
  4366 		    __INST(position) = nil; /* i.e. do not know */
  4319                 }
  4367 		}
  4320                 RETURN ( self );
  4368 		RETURN ( self );
  4321             }
  4369 	    }
  4322             __INST(position) = nil; /* i.e. do not know */
  4370 	    __INST(position) = nil; /* i.e. do not know */
  4323             __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4371 	    error = __mkSmallInteger(__threadErrno);
  4324         }
  4372 	}
  4325     }
  4373     }
  4326 out:;
  4374 out:;
  4327 %}.
  4375 %}.
  4328     lastErrorNumber notNil ifTrue:[self writeError. ^ self.].
  4376     error notNil ifTrue:[
       
  4377 	lastErrorNumber := error.
       
  4378 	self writeError:error.
       
  4379 	^ self
       
  4380     ].
  4329     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4381     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4330     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4382     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4331     self argumentMustBeInteger
  4383     self argumentMustBeInteger
  4332 ! !
  4384 ! !
  4333 
  4385 
  4533 
  4585 
  4534 open:aPath withMode:openModeString
  4586 open:aPath withMode:openModeString
  4535     "low level open; opens the file/device and sets the handle instance
  4587     "low level open; opens the file/device and sets the handle instance
  4536      variable. Careful: this does not care for any other state."
  4588      variable. Careful: this does not care for any other state."
  4537 
  4589 
  4538     |ok|
  4590     |ok error|
  4539 
  4591 
  4540     ok := false.
  4592     ok := false.
  4541 %{
  4593 %{
  4542     FILE *f;
  4594     FILE *f;
  4543     OBJ fp;
  4595     OBJ fp;
  4559 	    f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString));
  4611 	    f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString));
  4560 	} while ((f == NULL) && (__threadErrno == EINTR));
  4612 	} while ((f == NULL) && (__threadErrno == EINTR));
  4561 	__END_INTERRUPTABLE__
  4613 	__END_INTERRUPTABLE__
  4562 #endif /* UNIX */
  4614 #endif /* UNIX */
  4563 	if (f == NULL) {
  4615 	if (f == NULL) {
  4564 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4616 	    error = __mkSmallInteger(__threadErrno);
  4565 	} else {
  4617 	} else {
  4566 	    if (@global(FileOpenTrace) == true) {
  4618 	    if (@global(FileOpenTrace) == true) {
  4567 		fprintf(stderr, "fopen %s [ExternalStream] -> %"_lx_"\n", __stringVal(aPath), (INT)f);
  4619 		fprintf(stderr, "fopen %s [ExternalStream] -> %"_lx_"\n", __stringVal(aPath), (INT)f);
  4568 	    }
  4620 	    }
  4569 	    fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp);
  4621 	    fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp);
  4570 	    __INST(handleType) = @symbol(filePointer);
  4622 	    __INST(handleType) = @symbol(filePointer);
  4571 	    ok = true;
  4623 	    ok = true;
  4572 	}
  4624 	}
  4573     }
  4625     }
  4574 %}.
  4626 %}.
  4575     ok ifFalse:[
  4627     ok ifTrue:[
       
  4628 	position := 0.
       
  4629 	Lobby register:self.
       
  4630 	^ self.
       
  4631     ].
       
  4632     error notNil ifTrue:[
  4576 	"
  4633 	"
  4577 	 the open failed for some reason ...
  4634 	 the open failed for some reason ...
  4578 	"
  4635 	"
  4579 	^ self openError:lastErrorNumber.
  4636 	lastErrorNumber := error.
  4580     ].
  4637 	self openError:error.
  4581     position := 0.
  4638     ].
  4582     Lobby register:self.
  4639     self primitiveFailed.
  4583 !
  4640 !
  4584 
  4641 
  4585 reOpen
  4642 reOpen
  4586     "USERS WILL NEVER INVOKE THIS METHOD
  4643     "USERS WILL NEVER INVOKE THIS METHOD
  4587      sent after snapin to reopen streams.
  4644      sent after snapin to reopen streams.
  4738     "return the next element; advance read position.
  4795     "return the next element; advance read position.
  4739      In binary mode, an integer is returned, otherwise a character.
  4796      In binary mode, an integer is returned, otherwise a character.
  4740      If there are no more elements, either an exception is thrown or nil is returned
  4797      If there are no more elements, either an exception is thrown or nil is returned
  4741      - see #pastEndRead."
  4798      - see #pastEndRead."
  4742 
  4799 
  4743     |c|
  4800     |c error|
  4744 %{
  4801 %{
  4745     FILEPOINTER f;
  4802     FILEPOINTER f;
  4746     int ret, _buffered;
  4803     int ret, _buffered;
  4747     OBJ pos, fp;
  4804     OBJ pos, fp;
  4748     unsigned char ch;
  4805     unsigned char ch;
  4778 		RETURN ( __MKCHARACTER(ch) );
  4835 		RETURN ( __MKCHARACTER(ch) );
  4779 	    }
  4836 	    }
  4780 
  4837 
  4781 	    __INST(position) = nil;
  4838 	    __INST(position) = nil;
  4782 	    if (ret < 0) {
  4839 	    if (ret < 0) {
  4783 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4840 		error = __mkSmallInteger(__threadErrno);
  4784 	    } else /* ret == 0 */ {
  4841 	    } else /* ret == 0 */ {
  4785 		__INST(hitEOF) = true;
  4842 		__INST(hitEOF) = true;
  4786 	    }
  4843 	    }
  4787 	}
  4844 	}
  4788     }
  4845     }
  4789 %}.
  4846 %}.
  4790     hitEOF == true ifTrue:[^ self pastEndRead].
  4847     hitEOF == true ifTrue:[^ self pastEndRead].
  4791     lastErrorNumber notNil ifTrue:[^ self readError].
  4848     error notNil ifTrue:[
       
  4849 	lastErrorNumber := error.
       
  4850 	^ self readError:error
       
  4851     ].
  4792     handle isNil ifTrue:[^ self errorNotOpen].
  4852     handle isNil ifTrue:[^ self errorNotOpen].
  4793     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4853     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4794 
  4854 
  4795     readAhead notNil ifTrue:[
  4855     readAhead notNil ifTrue:[
  4796 	c := readAhead.
  4856 	c := readAhead.
  4835     "return the next element; advance read position.
  4895     "return the next element; advance read position.
  4836      In binary mode, an integer is returned, otherwise a character.
  4896      In binary mode, an integer is returned, otherwise a character.
  4837      If there are no more elements, nil is returned.
  4897      If there are no more elements, nil is returned.
  4838      This is #atEnd and #next in a single operation - to speed up some code"
  4898      This is #atEnd and #next in a single operation - to speed up some code"
  4839 
  4899 
  4840     |c|
  4900     |c error|
  4841 %{
  4901 %{
  4842     FILEPOINTER f;
  4902     FILEPOINTER f;
  4843     int ret, _buffered;
  4903     int ret, _buffered;
  4844     OBJ pos, fp;
  4904     OBJ pos, fp;
  4845     unsigned char ch;
  4905     unsigned char ch;
  4875 		RETURN ( __MKCHARACTER(ch) );
  4935 		RETURN ( __MKCHARACTER(ch) );
  4876 	    }
  4936 	    }
  4877 
  4937 
  4878 	    __INST(position) = nil;
  4938 	    __INST(position) = nil;
  4879 	    if (ret < 0) {
  4939 	    if (ret < 0) {
  4880 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  4940 		error = __mkSmallInteger(__threadErrno);
  4881 	    } else /* ret == 0 */ {
  4941 	    } else /* ret == 0 */ {
  4882 		__INST(hitEOF) = true;
  4942 		__INST(hitEOF) = true;
  4883 	    }
  4943 	    }
  4884 	}
  4944 	}
  4885     }
  4945     }
  4886 %}.
  4946 %}.
  4887     hitEOF == true ifTrue:[^ nil].
  4947     hitEOF == true ifTrue:[^ nil].
  4888     lastErrorNumber notNil ifTrue:[^ self readError].
  4948     error notNil ifTrue:[
       
  4949 	lastErrorNumber := error.
       
  4950 	^ self readError:error.
       
  4951     ].
  4889     handle isNil ifTrue:[^ self errorNotOpen].
  4952     handle isNil ifTrue:[^ self errorNotOpen].
  4890     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4953     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4891 
  4954 
  4892     readAhead notNil ifTrue:[
  4955     readAhead notNil ifTrue:[
  4893 	c := readAhead.
  4956 	c := readAhead.
  4908     "return the element to be read next without advancing read position.
  4971     "return the element to be read next without advancing read position.
  4909      In binary mode, an integer is returned, otherwise a character.
  4972      In binary mode, an integer is returned, otherwise a character.
  4910      If there are no more elements, either an exception is thrown or nil is returned
  4973      If there are no more elements, either an exception is thrown or nil is returned
  4911      - see #pastEndRead."
  4974      - see #pastEndRead."
  4912 
  4975 
       
  4976     |error|
  4913 %{
  4977 %{
  4914     FILEPOINTER f;
  4978     FILEPOINTER f;
  4915     unsigned char c;
  4979     unsigned char c;
  4916     int ret, _buffered;
  4980     int ret, _buffered;
  4917     OBJ fp;
  4981     OBJ fp;
  4948 		    RETURN ( __mkSmallInteger(c) );
  5012 		    RETURN ( __mkSmallInteger(c) );
  4949 		}
  5013 		}
  4950 		RETURN ( __MKCHARACTER(c) );
  5014 		RETURN ( __MKCHARACTER(c) );
  4951 	    }
  5015 	    }
  4952 	    if (ret < 0) {
  5016 	    if (ret < 0) {
  4953 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5017 		error = __mkSmallInteger(__threadErrno);
  4954 	    } else /* ret == 0 */ {
  5018 	    } else /* ret == 0 */ {
  4955 		__INST(hitEOF) = true;
  5019 		__INST(hitEOF) = true;
  4956 	    }
  5020 	    }
  4957 	}
  5021 	}
  4958     }
  5022     }
  4959 %}.
  5023 %}.
  4960     hitEOF == true ifTrue:[^ self pastEndRead].
  5024     hitEOF == true ifTrue:[^ self pastEndRead].
  4961     lastErrorNumber notNil ifTrue:[^ self readError].
  5025     error notNil ifTrue:[
       
  5026 	lastErrorNumber := error.
       
  5027 	^ self readError:error.
       
  5028     ].
  4962     handle isNil ifTrue:[^ self errorNotOpen].
  5029     handle isNil ifTrue:[^ self errorNotOpen].
  4963     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5030     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4964 
  5031 
  4965     readAhead isNil ifTrue:[
  5032     readAhead isNil ifTrue:[
  4966 	readAhead := self nextOrNil.
  5033 	readAhead := self nextOrNil.
  4975     "return the element to be read next without advancing read position.
  5042     "return the element to be read next without advancing read position.
  4976      In binary mode, an integer is returned, otherwise a character.
  5043      In binary mode, an integer is returned, otherwise a character.
  4977      If there are no more elements, nil is returned.
  5044      If there are no more elements, nil is returned.
  4978      Same as #atEnd and #peek in a single operation - speeding up some code"
  5045      Same as #atEnd and #peek in a single operation - speeding up some code"
  4979 
  5046 
       
  5047     |error|
  4980 %{
  5048 %{
  4981     FILEPOINTER f;
  5049     FILEPOINTER f;
  4982     unsigned char c;
  5050     unsigned char c;
  4983     int ret, _buffered;
  5051     int ret, _buffered;
  4984     OBJ fp;
  5052     OBJ fp;
  5015 		    RETURN ( __mkSmallInteger(c) );
  5083 		    RETURN ( __mkSmallInteger(c) );
  5016 		}
  5084 		}
  5017 		RETURN ( __MKCHARACTER(c) );
  5085 		RETURN ( __MKCHARACTER(c) );
  5018 	    }
  5086 	    }
  5019 	    if (ret < 0) {
  5087 	    if (ret < 0) {
  5020 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5088 		error = __mkSmallInteger(__threadErrno);
  5021 	    } else /* ret == 0 */ {
  5089 	    } else /* ret == 0 */ {
  5022 		__INST(hitEOF) = true;
  5090 		__INST(hitEOF) = true;
  5023 	    }
  5091 	    }
  5024 	}
  5092 	}
  5025     }
  5093     }
  5026 %}.
  5094 %}.
  5027     hitEOF == true ifTrue:[^ nil].
  5095     hitEOF == true ifTrue:[^ nil].
  5028     lastErrorNumber notNil ifTrue:[^ self readError].
  5096     error notNil ifTrue:[
       
  5097 	lastErrorNumber := error.
       
  5098 	^ self readError:error.
       
  5099     ].
  5029     handle isNil ifTrue:[^ self errorNotOpen].
  5100     handle isNil ifTrue:[^ self errorNotOpen].
  5030     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5101     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5031 
  5102 
  5032     readAhead isNil ifTrue:[
  5103     readAhead isNil ifTrue:[
  5033 	readAhead := self nextOrNil.
  5104 	readAhead := self nextOrNil.
  5041 
  5112 
  5042     |answerStream buffer count|
  5113     |answerStream buffer count|
  5043 
  5114 
  5044     buffer := self contentsSpecies new:4096.
  5115     buffer := self contentsSpecies new:4096.
  5045     [self atEnd] whileFalse:[
  5116     [self atEnd] whileFalse:[
  5046         count := self nextAvailableBytes:4096 into:buffer startingAt:1.
  5117 	count := self nextAvailableBytes:4096 into:buffer startingAt:1.
  5047         count ~~ 0 ifTrue:[
  5118 	count ~~ 0 ifTrue:[
  5048             answerStream isNil ifTrue:[
  5119 	    answerStream isNil ifTrue:[
  5049                 answerStream := WriteStream with:buffer.
  5120 		answerStream := WriteStream with:buffer.
  5050                 answerStream position:count.
  5121 		answerStream position:count.
  5051                 buffer := self contentsSpecies new:4096.
  5122 		buffer := self contentsSpecies new:4096.
  5052             ] ifFalse:[
  5123 	    ] ifFalse:[
  5053                 answerStream nextPutAll:buffer startingAt:1 to:count.
  5124 		answerStream nextPutAll:buffer startingAt:1 to:count.
  5054             ].
  5125 	    ].
  5055         ].
  5126 	].
  5056     ].
  5127     ].
  5057     answerStream isNil ifTrue:[^ self contentsSpecies new].
  5128     answerStream isNil ifTrue:[^ self contentsSpecies new].
  5058     ^ answerStream contents
  5129     ^ answerStream contents
  5059 
  5130 
  5060     "
  5131     "
  5532 
  5603 
  5533 nextPut:aCharacter
  5604 nextPut:aCharacter
  5534     "write the argument, aCharacter - return nil if failed, self if ok.
  5605     "write the argument, aCharacter - return nil if failed, self if ok.
  5535      Only single-byte characters are currently supported"
  5606      Only single-byte characters are currently supported"
  5536 
  5607 
       
  5608     |error|
  5537 %{
  5609 %{
  5538     FILEPOINTER f;
  5610     FILEPOINTER f;
  5539     unsigned codePoint;
  5611     unsigned codePoint;
  5540     unsigned char c;
  5612     unsigned char c;
  5541     int cnt, _buffered;
  5613     int cnt, _buffered;
  5580 			    } else {
  5652 			    } else {
  5581 				__INST(position) = nil; /* i.e. do not know */
  5653 				__INST(position) = nil; /* i.e. do not know */
  5582 			    }
  5654 			    }
  5583 			    RETURN ( self );
  5655 			    RETURN ( self );
  5584 			}
  5656 			}
  5585 			__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5657 			error = __mkSmallInteger(__threadErrno);
  5586 		    }
  5658 		    }
  5587 		}
  5659 		}
  5588 	    } else {
  5660 	    } else {
  5589 		if (__isSmallInteger(aCharacter)) {
  5661 		if (__isSmallInteger(aCharacter)) {
  5590 		    c = __intVal(aCharacter);
  5662 		    c = __intVal(aCharacter);
  5593 	    }
  5665 	    }
  5594 	}
  5666 	}
  5595     }
  5667     }
  5596 out: ;
  5668 out: ;
  5597 %}.
  5669 %}.
  5598     lastErrorNumber notNil ifTrue:[self writeError. ^ self].
  5670     error notNil ifTrue:[
       
  5671 	lastErrorNumber := error.
       
  5672 	self writeError:error.
       
  5673 	^ self
       
  5674     ].
  5599     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5675     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5600     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5676     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5601     binary == true ifFalse:[
  5677     binary == true ifFalse:[
  5602 	(aCharacter isCharacter not
  5678 	(aCharacter isCharacter not
  5603 	or:[aCharacter codePoint > 16rFF]) ifTrue:[
  5679 	or:[aCharacter codePoint > 16rFF]) ifTrue:[
  5619 nextPutAll:aCollection
  5695 nextPutAll:aCollection
  5620     "write all elements of the argument, aCollection.
  5696     "write all elements of the argument, aCollection.
  5621      Reimplemented for speed when writing strings or byteArrays.
  5697      Reimplemented for speed when writing strings or byteArrays.
  5622      For others, falls back to general method in superclass."
  5698      For others, falls back to general method in superclass."
  5623 
  5699 
       
  5700     |error|
  5624 %{
  5701 %{
  5625     FILEPOINTER f;
  5702     FILEPOINTER f;
  5626     INT len, cnt;
  5703     INT len, cnt;
  5627     OBJ fp;
  5704     OBJ fp;
  5628     int _buffered;
  5705     int _buffered;
  5693 		} else {
  5770 		} else {
  5694 		    __INST(position) = nil; /* i.e. do not know */
  5771 		    __INST(position) = nil; /* i.e. do not know */
  5695 		}
  5772 		}
  5696 		RETURN (self);
  5773 		RETURN (self);
  5697 	    }
  5774 	    }
  5698 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5775 	    error = __mkSmallInteger(__threadErrno);
  5699 	}
  5776 	}
  5700     }
  5777     }
  5701 out: ;
  5778 out: ;
  5702 %}.
  5779 %}.
  5703     lastErrorNumber notNil ifTrue:[self writeError. ^ self].
  5780     error notNil ifTrue:[
       
  5781 	lastErrorNumber := error.
       
  5782 	self writeError:error.
       
  5783 	^ self
       
  5784     ].
  5704     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5785     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5705     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5786     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5706 
  5787 
  5707     ^ super nextPutAll:aCollection
  5788     ^ super nextPutAll:aCollection
  5708 !
  5789 !
  5709 
  5790 
  5710 nextPutAll:aCollection startingAt:start to:stop
  5791 nextPutAll:aCollection startingAt:start to:stop
  5711     "write a range of elements of the argument, aCollection.
  5792     "write a range of elements of the argument, aCollection.
  5712      Reimplemented for speed when writing strings or byteArrays.
  5793      Reimplemented for speed when writing strings or byteArrays.
  5713      For others, falls back to general method in superclass."
  5794      For others, falls back to general method in superclass."
       
  5795 
       
  5796      |error|
  5714 
  5797 
  5715 %{
  5798 %{
  5716     FILEPOINTER f;
  5799     FILEPOINTER f;
  5717     int offs, len, cnt, iStart, iStop, _buffered;
  5800     int offs, len, cnt, iStart, iStop, _buffered;
  5718     OBJ fp;
  5801     OBJ fp;
  5794 		} else {
  5877 		} else {
  5795 		    __INST(position) = nil; /* i.e. do not know */
  5878 		    __INST(position) = nil; /* i.e. do not know */
  5796 		}
  5879 		}
  5797 		RETURN (self);
  5880 		RETURN (self);
  5798 	    }
  5881 	    }
  5799 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5882 	    error = __mkSmallInteger(__threadErrno);
  5800 	}
  5883 	}
  5801     }
  5884     }
  5802 out: ;
  5885 out: ;
  5803 %}.
  5886 %}.
  5804     lastErrorNumber notNil ifTrue:[self writeError. ^ self].
  5887     error notNil ifTrue:[
       
  5888 	lastErrorNumber := error.
       
  5889 	self writeError:error.
       
  5890 	^ self
       
  5891     ].
  5805     ^ super nextPutAll:aCollection startingAt:start to:stop
  5892     ^ super nextPutAll:aCollection startingAt:start to:stop
  5806 !
  5893 !
  5807 
  5894 
  5808 nextPutAllUnicode:aString
  5895 nextPutAllUnicode:aString
  5809     "normal streams can not handle multi-byte characters, so convert them to utf8.
  5896     "normal streams can not handle multi-byte characters, so convert them to utf8.
  5810      This is needed, so that you can do ('something' asUnicode16String errorPrintCR)"
  5897      This is needed, so that you can do ('something' asUnicode16String errorPrintCR)"
  5811 
  5898 
  5812     aString do:[:eachCharacter|
  5899     aString do:[:eachCharacter|
  5813         self nextPutUtf8:eachCharacter.
  5900 	self nextPutUtf8:eachCharacter.
  5814     ].
  5901     ].
  5815 
  5902 
  5816     "
  5903     "
  5817         'Bönnigheim' asUnicode16String errorPrintCR
  5904 	'Bönnigheim' asUnicode16String errorPrintCR
  5818     "
  5905     "
  5819 !
  5906 !
  5820 
  5907 
  5821 nextPutUnicode:aCharacter
  5908 nextPutUnicode:aCharacter
  5822     "normal streams can not handle multi-byte characters, so convert them to utf8"
  5909     "normal streams can not handle multi-byte characters, so convert them to utf8"
  5831     |codePoint|
  5918     |codePoint|
  5832 
  5919 
  5833     codePoint := aCharacter codePoint.
  5920     codePoint := aCharacter codePoint.
  5834     (codePoint <= 16rD7FF
  5921     (codePoint <= 16rD7FF
  5835       or:[codePoint >= 16rE000 and:[codePoint <= 16rFFFF]]) ifTrue:[
  5922       or:[codePoint >= 16rE000 and:[codePoint <= 16rFFFF]]) ifTrue:[
  5836         self nextPutShort:codePoint MSB:true.
  5923 	self nextPutShort:codePoint MSB:true.
  5837     ] ifFalse:[codePoint <= 16r10FFFF ifTrue:[
  5924     ] ifFalse:[codePoint <= 16r10FFFF ifTrue:[
  5838         |highBits lowBits|
  5925 	|highBits lowBits|
  5839 
  5926 
  5840         codePoint := codePoint - 16r100000.
  5927 	codePoint := codePoint - 16r100000.
  5841         highBits := codePoint bitShift:-10.
  5928 	highBits := codePoint bitShift:-10.
  5842         lowBits := codePoint bitAnd:16r3FF.
  5929 	lowBits := codePoint bitAnd:16r3FF.
  5843         self nextPutShort:highBits+16rD800 MSB:true.
  5930 	self nextPutShort:highBits+16rD800 MSB:true.
  5844         self nextPutShort:lowBits+16rDC00 MSB:true.
  5931 	self nextPutShort:lowBits+16rDC00 MSB:true.
  5845     ] ifFalse:[
  5932     ] ifFalse:[
  5846         EncodingError raiseWith:aCharacter errorString:'Character cannot be encoded as UTF-16'.
  5933 	EncodingError raiseWith:aCharacter errorString:'Character cannot be encoded as UTF-16'.
  5847     ]].
  5934     ]].
  5848 
  5935 
  5849     "
  5936     "
  5850         (FileStream newTemporary
  5937 	(FileStream newTemporary
  5851             nextPutUtf16:$B;
  5938 	    nextPutUtf16:$B;
  5852             nextPutUtf16:$Ä; 
  5939 	    nextPutUtf16:$Ä;
  5853             nextPutUtf16:(Character codePoint:16r10CCCC);
  5940 	    nextPutUtf16:(Character codePoint:16r10CCCC);
  5854             reset;
  5941 	    reset;
  5855             binary;
  5942 	    binary;
  5856             contents)
  5943 	    contents)
  5857     "
  5944     "
  5858 ! !
  5945 ! !
  5859 
  5946 
  5860 !ExternalStream class methodsFor:'documentation'!
  5947 !ExternalStream class methodsFor:'documentation'!
  5861 
  5948 
  5862 version
  5949 version
  5863     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.380 2014-02-12 14:18:02 stefan Exp $'
  5950     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.381 2014-04-03 12:58:08 stefan Exp $'
  5864 !
  5951 !
  5865 
  5952 
  5866 version_CVS
  5953 version_CVS
  5867     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.380 2014-02-12 14:18:02 stefan Exp $'
  5954     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.381 2014-04-03 12:58:08 stefan Exp $'
  5868 ! !
  5955 ! !
  5869 
  5956 
  5870 
  5957 
  5871 ExternalStream initialize!
  5958 ExternalStream initialize!