ExternalStream.st
changeset 16368 1efe4d36fd3f
parent 16308 4f0cb8a09d1d
child 16373 9b9827530bf4
equal deleted inserted replaced
16367:e08c79499faa 16368:1efe4d36fd3f
     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 'From Smalltalk/X, Version:6.2.3.0 on 18-04-2014 at 00:36:23'                   !
       
    13 
    12 "{ Package: 'stx:libbasic' }"
    14 "{ Package: 'stx:libbasic' }"
    13 
    15 
    14 ReadWriteStream subclass:#ExternalStream
    16 ReadWriteStream subclass:#ExternalStream
    15 	instanceVariableNames:'handleType handle mode buffered binary eolMode hitEOF didWrite
    17 	instanceVariableNames:'handleType handle mode buffered binary eolMode hitEOF didWrite
    16 		lastErrorNumber readAhead'
    18 		lastErrorNumber readAhead'
   215 #else
   217 #else
   216 # define OPT_FSEEK(f, pos, whence)      /* nothing */
   218 # define OPT_FSEEK(f, pos, whence)      /* nothing */
   217 #endif
   219 #endif
   218 
   220 
   219 #ifdef WIN32
   221 #ifdef WIN32
   220 # ifdef __BORLANDC__
   222 #  define READ(ret, f, cp, n, handleType) { \
   221    int _rtl_read();
   223         if (handleType == @symbol(socketHandle)) { \
   222    int _rtl_write();
   224           (ret) = __STX_WSA_NOINT_CALL4("recv", recv, (f), (cp), (n), 0); \
   223 
       
   224 #  define READ(ret,f, cp, n, handleType) \
       
   225       { int __res;\
       
   226         HANDLE h; \
       
   227         h = _get_osfhandle(fileno(f)); \
       
   228         if ((handleType == @symbol(socketFilePointer)) \
       
   229         || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
       
   230           (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
       
   231         } else { \
   225         } else { \
   232           (ret) = __STX_C_NOINT_CALL3("_rtl_read", _rtl_read, fileno(f), (cp), (n));\
   226           HANDLE h = _get_osfhandle(fileno(f)); \
   233         } \
   227           if (handleType == @symbol(socketFilePointer)) { \
   234       }
       
   235 
       
   236 #  define WRITE(ret,f, cp, n, handleType) \
       
   237       { int __res;\
       
   238         HANDLE h; \
       
   239         h = _get_osfhandle(fileno(f)); \
       
   240         if ((handleType == @symbol(socketFilePointer)) \
       
   241         || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
       
   242           (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
       
   243         } else { \
       
   244           (ret) = __STX_C_NOINT_CALL3("_rtl_write", _rtl_write, fileno(f), (cp), (n));\
       
   245         } \
       
   246       }
       
   247 
       
   248 # else /* MSC */
       
   249 
       
   250 #  define READ(ret,f, cp, n, handleType) \
       
   251       { int __res;\
       
   252         int fd; \
       
   253         HANDLE h; \
       
   254         fd = fileno(f); \
       
   255         if ((handleType == @symbol(socketFileDescriptor)) \
       
   256          || ((handleType == nil) && (ioctlsocket((SOCKET)fd,FIONREAD,&__res)==0))) { \
       
   257           (ret) = __STX_WSA_NOINT_CALL4("recv", recv, fd, (cp), (n), 0);\
       
   258         } else { \
       
   259           h = _get_osfhandle(fd); \
       
   260           if ((handleType == @symbol(socketFilePointer)) \
       
   261           || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
       
   262             (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
   228             (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\
   263           } else { \
   229           } else { \
       
   230             int __res; \
   264             (ret) = __STX_API_NOINT_CALL5("ReadFile", ReadFile, h, (cp), (n), &__res, 0);\
   231             (ret) = __STX_API_NOINT_CALL5("ReadFile", ReadFile, h, (cp), (n), &__res, 0);\
   265             if (ret) \
   232             (ret) = (ret) ? __res : -1; \
   266               ret = __res; \
       
   267           } \
   233           } \
   268         } \
   234         } \
   269       }
   235       }
   270 #  define WRITE(ret,f, cp, n, handleType) \
   236 
   271       { int __res;\
   237 #  define WRITE(ret, f, cp, n, handleType) { \
   272         int fd; \
   238         if (handleType == @symbol(socketHandle)) { \
   273         HANDLE h; \
   239           (ret) = __STX_WSA_NOINT_CALL4("send", send, (f), (cp), (n), 0); \
   274         fd = fileno(f); \
       
   275         if ((handleType == @symbol(socketFileDescriptor)) \
       
   276          || ((handleType == nil) && (ioctlsocket((SOCKET)fd,FIONREAD,&__res)==0))) { \
       
   277           (ret) = __STX_WSA_NOINT_CALL4("send", send, fd, (cp), (n), 0);\
       
   278         } else {\
   240         } else {\
   279           h = _get_osfhandle(fd); \
   241           HANDLE h = _get_osfhandle(fileno(f)); \
   280           if ((handleType == @symbol(socketFilePointer)) \
   242           if (handleType == @symbol(socketFilePointer)) { \
   281           || ((handleType == nil) && (ioctlsocket((SOCKET)h,FIONREAD,&__res)==0))) { \
       
   282             (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
   243             (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\
   283           } else {\
   244           } else {\
       
   245             int __res; \
   284             (ret) = __STX_API_NOINT_CALL5("WriteFile", WriteFile, h, (cp), (n), &__res, 0);\
   246             (ret) = __STX_API_NOINT_CALL5("WriteFile", WriteFile, h, (cp), (n), &__res, 0);\
   285             if (ret) \
   247             (ret) = (ret) ? __res : -1; \
   286               ret = __res; \
       
   287           } \
   248           } \
   288         } \
   249         } \
   289       }
   250       }
   290 # endif /* MSC */
       
   291 
   251 
   292 # define FFLUSH(fp)             fflush(fp)
   252 # define FFLUSH(fp)             fflush(fp)
   293 # undef STDIO_NEEDS_FSEEK
   253 # undef STDIO_NEEDS_FSEEK
   294 # define FILEPOINTER            FILE *
   254 # define FILEPOINTER            FILE *
   295 # define FILENO(f)              fileno(f)
   255 # define FILENO(f)              fileno(f)
   310 
   270 
   311 # define __UNGETC__(c, f, isBuffered)                   \
   271 # define __UNGETC__(c, f, isBuffered)                   \
   312     if (isBuffered) {                                   \
   272     if (isBuffered) {                                   \
   313         ungetc((c), (f));                               \
   273         ungetc((c), (f));                               \
   314     } else {                                            \
   274     } else {                                            \
   315       __INST(readAhead) = __mkSmallInteger((c));            \
   275       __INST(readAhead) = __mkSmallInteger((c));        \
   316     }
   276     }
   317 
   277 
   318 # define __READBYTE__(ret, f, buf, isBuffered, handleType)          \
   278 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \
   319     if (isBuffered) {                                   \
   279     if (isBuffered) {                                   \
   320         for (;;) {                                      \
   280         for (;;) {                                      \
   321             CLEAR_ERRNO;                                \
   281             CLEAR_ERRNO;                                \
   322             (ret) = getc(f);                            \
   282             (ret) = getc(f);                            \
   323             if ((ret) >= 0) {                           \
   283             if ((ret) >= 0) {                           \
   340             __INST(readAhead) = nil;                    \
   300             __INST(readAhead) = nil;                    \
   341             (ret) = 1;                                  \
   301             (ret) = 1;                                  \
   342         } else {                                        \
   302         } else {                                        \
   343             for (;;) {                                  \
   303             for (;;) {                                  \
   344                 CLEAR_ERRNO;                            \
   304                 CLEAR_ERRNO;                            \
   345                 READ(ret,f, buf, 1, handleType);                    \
   305                 READ(ret, f, buf, 1, handleType);       \
   346                 if ((ret) >= 0 || __threadErrno != EINTR)       \
   306                 if ((ret) >= 0 || __threadErrno != EINTR) \
   347                     break;                              \
   307                     break;                              \
   348             }                                           \
   308             }                                           \
   349         }                                               \
   309         }                                               \
   350     }
   310     }
   351 
   311 
   360         while (__offs < (cnt)) {                        \
   320         while (__offs < (cnt)) {                        \
   361             CLEAR_ERRNO;                                \
   321             CLEAR_ERRNO;                                \
   362             (ret) = getc(f);                            \
   322             (ret) = getc(f);                            \
   363             if ((ret) < 0) {                            \
   323             if ((ret) < 0) {                            \
   364                 if (ferror(f)) {                        \
   324                 if (ferror(f)) {                        \
   365                     if (__threadErrno == EINTR) {               \
   325                     if (__threadErrno == EINTR) {       \
   366                         clearerr(f);                    \
   326                         clearerr(f);                    \
   367                         continue;                       \
   327                         continue;                       \
   368                     }                                   \
   328                     }                                   \
   369                 } else {                                \
   329                 } else {                                \
   370                     (ret) = 0;                          \
   330                     (ret) = 0;                          \
   384                 (buf)[__offs] = __intVal(rA);           \
   344                 (buf)[__offs] = __intVal(rA);           \
   385                 __INST(readAhead) = nil;                \
   345                 __INST(readAhead) = nil;                \
   386                 (ret) = 1;                              \
   346                 (ret) = 1;                              \
   387             } else {                                    \
   347             } else {                                    \
   388                 CLEAR_ERRNO;                            \
   348                 CLEAR_ERRNO;                            \
   389                 READ(ret,f, (buf)+__offs, (cnt)-__offs, handleType); \
   349                 READ(ret, f, (buf)+__offs, (cnt)-__offs, handleType); \
   390                 if ((ret) <= 0) {                       \
   350                 if ((ret) <= 0) {                       \
   391                     if ((ret) < 0 && __threadErrno == EINTR) {  \
   351                     if ((ret) < 0 && __threadErrno == EINTR) {  \
   392                         continue;                       \
   352                         continue;                       \
   393                     }                                   \
   353                     }                                   \
   394                     break;                              \
   354                     break;                              \
   410         while (__offs < (cnt)) {                        \
   370         while (__offs < (cnt)) {                        \
   411             CLEAR_ERRNO;                                \
   371             CLEAR_ERRNO;                                \
   412             (ret) = getc(f);                            \
   372             (ret) = getc(f);                            \
   413             if ((ret) < 0) {                            \
   373             if ((ret) < 0) {                            \
   414                 if (ferror(f)) {                        \
   374                 if (ferror(f)) {                        \
   415                     if (__threadErrno == EINTR) {               \
   375                     if (__threadErrno == EINTR) {       \
   416                         clearerr(f);                    \
   376                         clearerr(f);                    \
   417                         continue;                       \
   377                         continue;                       \
   418                     }                                   \
   378                     }                                   \
   419                 } else {                                \
   379                 } else {                                \
   420                     (ret) = 0;                          \
   380                     (ret) = 0;                          \
   430             OBJ rA = __INST(readAhead);                 \
   390             OBJ rA = __INST(readAhead);                 \
   431             if (rA != nil) {                            \
   391             if (rA != nil) {                            \
   432                 (buf)[__offs] = __intVal(rA);           \
   392                 (buf)[__offs] = __intVal(rA);           \
   433                 __INST(readAhead) = nil;                \
   393                 __INST(readAhead) = nil;                \
   434                 (ret) = 1;                              \
   394                 (ret) = 1;                              \
   435                 __offs += (ret);                        \
   395                 __offs ++;                              \
   436                 continue;                               \
   396                 continue;                               \
   437             }                                           \
   397             }                                           \
   438             CLEAR_ERRNO;                                \
   398             CLEAR_ERRNO;                                \
   439             {                                           \
   399             {                                           \
   440               int res;                                  \
   400               int res = 0;                              \
   441               if ((handleType == @symbol(socketFilePointer)) \
   401               if ((handleType == @symbol(socketFilePointer) && (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res), 1)) \
   442                || ((handleType == nil) && (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res)==0))) { \
   402                   || (handleType == @symbol(socketHandle) && (ioctlsocket((SOCKET)(f), FIONREAD, &res), 1)) \
       
   403                   || (handleType == @symbol(pipeFilePointer) && (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)), 1)) { \
   443                   if (res > 0) {                        \
   404                   if (res > 0) {                        \
   444                       if (res > ((cnt)-__offs))         \
   405                       if (res > ((cnt)-__offs))         \
   445                         res = (cnt)-__offs;             \
   406                           res = (cnt)-__offs;           \
   446                       READ(ret,f, (buf)+__offs, res, handleType);   \
   407                       READ(ret, f, (buf)+__offs, res, handleType); \
   447                   } else {                              \
   408                   } else {                              \
   448                       (ret) = 0;                        \
   409                       (ret) = 0;                        \
       
   410                       break;                            \
   449                   }                                     \
   411                   }                                     \
   450               } else if ((handleType == @symbol(pipeFilePointer)) \
       
   451                          || ((handleType == nil) && (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)))) { \
       
   452                   if (res > 0) {                        \
       
   453                       if (res > ((cnt)-__offs))         \
       
   454                         res = (cnt)-__offs;             \
       
   455                       READ(ret,f, (buf)+__offs, res, handleType);   \
       
   456                   } else                                \
       
   457                       ret = 0;                          \
       
   458               } else {                                  \
   412               } else {                                  \
   459                   READ(ret,f, (buf)+__offs, (cnt)-__offs, handleType); \
   413                   READ(ret, f, (buf)+__offs, (cnt)-__offs, handleType); \
   460               }                                         \
   414               }                                         \
   461             }                                           \
   415             }                                           \
   462             if ((ret) < 0) {                            \
   416             if ((ret) < 0 && __threadErrno == EINTR)    \
   463                 if (__threadErrno == EINTR) {                   \
   417                 continue;                               \
   464                     continue;                           \
       
   465                 }                                       \
       
   466                 break;                                  \
       
   467             }                                           \
       
   468             __offs += (ret);                            \
   418             __offs += (ret);                            \
   469             break;                                      \
       
   470         }                                               \
   419         }                                               \
   471         if (__offs > 0)                                 \
   420         if (__offs > 0)                                 \
   472             (ret) = __offs;                             \
   421             (ret) = __offs;                             \
   473     }                                                   \
   422     }                                                   \
   474   }
   423   }
   524                         continue;                       \
   473                         continue;                       \
   525                     }                                   \
   474                     }                                   \
   526                     break;                              \
   475                     break;                              \
   527                 }                                       \
   476                 }                                       \
   528             }                                           \
   477             }                                           \
   529             if( (ret) > 0 ) {                               \
   478             if ((ret) > 0 ) {                           \
   530                 /* refetch */                               \
   479                 /* refetch */                               \
   531                 buf = (char *)(obj);               \
   480                 buf = (char *)(obj);               \
   532                 memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   481                 memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   533                 __offs += (ret);                            \
   482                 __offs += (ret);                            \
   534             } else {                                        \
   483             } else {                                        \
   538         if (__offs > 0)                                 \
   487         if (__offs > 0)                                 \
   539             (ret) = __offs;                             \
   488             (ret) = __offs;                             \
   540     }                                                   \
   489     }                                                   \
   541   }
   490   }
   542 
   491 
   543 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType)\
   492 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \
   544   {                                                  \
   493   {                                                  \
   545     int __ooffs = obj_offs;                          \
   494     int __ooffs = obj_offs;                          \
   546     int __offs = 0;                                  \
   495     int __offs = 0;                                  \
   547     char *buf = (char *)(obj);                       \
   496     char *buf = (char *)(obj);                       \
   548                                                      \
   497                                                      \
   575             OBJ rA = __INST(readAhead);              \
   524             OBJ rA = __INST(readAhead);              \
   576             if (rA != nil) {                         \
   525             if (rA != nil) {                         \
   577                 (buf)[__ooffs+__offs] = __intVal(rA);\
   526                 (buf)[__ooffs+__offs] = __intVal(rA);\
   578                 __INST(readAhead) = nil;             \
   527                 __INST(readAhead) = nil;             \
   579                 (ret) = 1;                           \
   528                 (ret) = 1;                           \
   580                 __offs += (ret);                     \
   529                 __offs++;                            \
   581                 continue;                            \
   530                 continue;                            \
   582             }                                        \
   531             }                                        \
   583             {                                        \
   532             {                                        \
   584                 int l;                               \
   533                 int res = 0;                         \
   585                 int res;                             \
   534                 int l = (cnt)-__offs;                \
   586                 CLEAR_ERRNO;                         \
   535                 CLEAR_ERRNO;                         \
   587                 l = (cnt)-__offs;                    \
   536                 if (l > IO_BUFFER_SIZE)              \
   588                 if ( l > IO_BUFFER_SIZE)             \
       
   589                     l = IO_BUFFER_SIZE;              \
   537                     l = IO_BUFFER_SIZE;              \
   590                 if (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res)==0) { \
   538                 if ((handleType == @symbol(socketFilePointer) && (ioctlsocket((SOCKET)_get_osfhandle(fileno(f)), FIONREAD, &res), 1)) \
       
   539                     || (handleType == @symbol(socketHandle) && (ioctlsocket((SOCKET)(f), FIONREAD, &res), 1)) \
       
   540                     || (handleType == @symbol(pipeFilePointer) && (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0,0,0,&res,0), 1))) { \
   591                     if (res > 0) {                   \
   541                     if (res > 0) {                   \
   592                         if (res > l)                 \
   542                         if (res > l) res = l;        \
   593                             res = l;                 \
   543                         READ(ret, f, __buf, res, handleType); \
   594                         READ(ret,f, __buf, res, handleType);     \
       
   595                     } else {                         \
   544                     } else {                         \
   596                         (ret) = 0;                   \
   545                         (ret) = 0;                   \
       
   546                         break;                       \
   597                     }                                \
   547                     }                                \
   598                 } else if (PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)) { \
       
   599                     if (res > 0) {                   \
       
   600                         if (res > l)                 \
       
   601                             res = l;                 \
       
   602                         READ(ret,f, __buf, res, handleType);     \
       
   603                     } else                           \
       
   604                         (ret) = 0;                   \
       
   605                 } else {                             \
   548                 } else {                             \
   606                     READ(ret,f, __buf, l, handleType);           \
   549                     READ(ret, f, __buf, l, handleType); \
   607                 }                                    \
   550                 }                                       \
   608                 if ((ret) < 0 && __threadErrno == EINTR) {   \
   551                 if ((ret) < 0 && __threadErrno == EINTR) \
   609                     continue;                        \
   552                     continue;                           \
   610                 }                                    \
   553             }                                           \
   611             }                                        \
   554             if ((ret) > 0) {                            \
   612             if( (ret) > 0 ) {                               \
   555                 buf = (char *)(obj);                    \
   613                 /* refetch */                               \
   556                 memcpy((buf)+__ooffs+__offs, __buf, (ret)); \
   614                 buf = (char *)(obj);               \
   557                 __offs += (ret);                        \
   615                 memcpy((buf)+__ooffs+__offs,__buf,(ret));   \
   558             } else {                                    \
   616                 __offs += (ret);                            \
   559                 (ret) = 0;                              \
   617             } else {                                        \
   560             }                                           \
   618                 (ret) = 0;                                  \
       
   619             }                                               \
       
   620             break;                                      \
       
   621         }                                               \
   561         }                                               \
   622         if (__offs > 0)                                 \
   562         if (__offs > 0)                                 \
   623             (ret) = __offs;                             \
   563             (ret) = __offs;                             \
   624     }                                                   \
   564     }                                                   \
   625   }
   565   }
   675         int __offs = 0;                                 \
   615         int __offs = 0;                                 \
   676         while (__offs < (cnt)) {                        \
   616         while (__offs < (cnt)) {                        \
   677             CLEAR_ERRNO;                                \
   617             CLEAR_ERRNO;                                \
   678             WRITE(ret,f, (buf)+__offs, (cnt)-__offs, handleType);   \
   618             WRITE(ret,f, (buf)+__offs, (cnt)-__offs, handleType);   \
   679             if (ret <= 0) {                             \
   619             if (ret <= 0) {                             \
   680                 if (ret < 0 && __threadErrno == EINTR) {        \
   620                 if (ret < 0 && __threadErrno == EINTR) { \
   681                     continue;                           \
   621                     continue;                           \
   682                 }                                       \
   622                 }                                       \
   683                 break;                                  \
   623                 break;                                  \
   684             }                                           \
   624             }                                           \
   685             __offs += (ret);                            \
   625             __offs += (ret);                            \
  1431       if the contents changed in the meantime.
  1371       if the contents changed in the meantime.
  1432       Therefore, it is a good idea to reopen files and check for these things at restart time.
  1372       Therefore, it is a good idea to reopen files and check for these things at restart time.
  1433 
  1373 
  1434     [Instance variables:]
  1374     [Instance variables:]
  1435 
  1375 
  1436 	handleType      <Symbol>        desribes what handle is:
  1376         handleType      <Symbol>        desribes what handle is:
  1437 					    win32: #fileHandle, #socketHandle,
  1377                                             win32: #fileHandle, #socketHandle,
  1438 						   #socketFileDescriptor
  1378                                                    #filePointer, #socketFilePointer, #pipeFilePointer
  1439 						   #filePointer, #socketFilePointer, #pipeFilePointer
  1379                                             unix: #filePointer, #socketFilePointer, #pipeFilePointer
  1440 					    unix: #filePointer, #socketFilePointer, #pipeFilePointer
  1380                                         needed for win32, which uses different APIs for the different handles (sigh)
  1441 					needed for win32, which uses different APIs for the different handles (sigh)
  1381         handle          <Integer>       used to be always a filePointer somehow mapped to an integer (FILE* - not the fd);
  1442 	handle          <Integer>       used to be always a filePointer somehow mapped to an integer (FILE* - not the fd);
  1382                                         now, either a filePointer or a handle (win32)
  1443 					now, either a filePointer or a handle (win32)
  1383         mode            <Symbol>        #readwrite, #readonly or #writeonly
  1444 	mode            <Symbol>        #readwrite, #readonly or #writeonly
  1384         buffered        <Boolean>       true, if buffered (i.e. collects characters - does
  1445 	buffered        <Boolean>       true, if buffered (i.e. collects characters - does
  1385                                         not output immediately)
  1446 					not output immediately)
  1386         binary          <Boolean>       true if in binary mode (reads bytes instead of chars)
  1447 	binary          <Boolean>       true if in binary mode (reads bytes instead of chars)
  1387         eolMode         <Symbol>        one of nil, #cr or #crlf.
  1448 	eolMode         <Symbol>        one of nil, #cr or #crlf.
  1388                                         determines how lines should be terminated.
  1449 					determines how lines should be terminated.
  1389                                         nil -> newLine (as in Unix);
  1450 					nil -> newLine (as in Unix);
  1390                                         #crlf -> with cr-lf (as in MSDOS)
  1451 					#crlf -> with cr-lf (as in MSDOS)
  1391                                         #cr -> with cr (as in VMS)
  1452 					#cr -> with cr (as in VMS)
  1392         hitEOF          <Boolean>       true, if EOF was reached
  1453 	hitEOF          <Boolean>       true, if EOF was reached
  1393 
  1454 
  1394         lastErrorNumber <Integer>       the value of errno (only valid right after the error -
  1455 	lastErrorNumber <Integer>       the value of errno (only valid right after the error -
  1395                                         updated with next i/o operation)
  1456 					updated with next i/o operation)
       
  1457 
  1396 
  1458     [Class variables:]
  1397     [Class variables:]
  1459 	Lobby           <Registry>      keeps track of used ext-streams (to free up FILE*'s)
  1398         Lobby           <Registry>      keeps track of used ext-streams (to free up FILE*'s)
  1460 
  1399 
  1461 	StreamErrorSignal       <Signal> parent of all stream errors (see Stream class)
  1400         StreamErrorSignal       <Signal> parent of all stream errors (see Stream class)
  1462 	InvalidReadSignal       <Signal> raised on read from writeonly stream
  1401         InvalidReadSignal       <Signal> raised on read from writeonly stream
  1463 	InvalidWriteSignal      <Signal> raised on write to readonly stream
  1402         InvalidWriteSignal      <Signal> raised on write to readonly stream
  1464 	InvalidModeSignal       <Signal> raised on text I/O with binary-stream
  1403         InvalidModeSignal       <Signal> raised on text I/O with binary-stream
  1465 					 or binary I/O with text-stream
  1404                                          or binary I/O with text-stream
  1466 	OpenErrorSignal         <Signal> raised if open fails
  1405         OpenErrorSignal         <Signal> raised if open fails
  1467 	StreamNotOpenSignal     <Signal> raised on I/O with non-open stream
  1406         StreamNotOpenSignal     <Signal> raised on I/O with non-open stream
  1468 
  1407 
  1469     Additional notes:
  1408     Additional notes:
  1470       This class is implemented using the underlying stdio-c library package, which
  1409       This class is implemented using the underlying stdio-c library package, which
  1471       has both advantages and disadvantages: since it is portable (posix defined), porting
  1410       has both advantages and disadvantages: since it is portable (posix defined), porting
  1472       ST/X to non-Unix machines is simplified. The disadvantage is that the stdio library
  1411       ST/X to non-Unix machines is simplified. The disadvantage is that the stdio library
  1496       fseek whenever we are about to read after write and vice versa.
  1435       fseek whenever we are about to read after write and vice versa.
  1497       Two macros (__READING__ and __WRITING__) have been defined to be used before every
  1436       Two macros (__READING__ and __WRITING__) have been defined to be used before every
  1498       fread/fgetc and fwrite/putc respectively.
  1437       fread/fgetc and fwrite/putc respectively.
  1499 
  1438 
  1500     [author:]
  1439     [author:]
  1501 	Claus Gittinger
  1440         Claus Gittinger
  1502 	Stefan Vogel (many, many fixes ...)
  1441         Stefan Vogel (many, many fixes ...)
  1503 
  1442 
  1504     [see also:]
  1443     [see also:]
  1505 	FileStream Socket PipeStream
  1444         FileStream Socket PipeStream
  1506 	Filename OperatingSystem
  1445         Filename OperatingSystem
  1507 "
  1446 "
  1508 !
  1447 !
  1509 
  1448 
  1510 examples
  1449 examples
  1511 "
  1450 "
  2094     "return the fileDescriptor of the receiver -
  2033     "return the fileDescriptor of the receiver -
  2095      notice: this one returns the underlying OSs fileDescriptor -
  2034      notice: this one returns the underlying OSs fileDescriptor -
  2096      this may not be available on all platforms (i.e. non unix systems)."
  2035      this may not be available on all platforms (i.e. non unix systems)."
  2097 
  2036 
  2098 %{
  2037 %{
  2099     OBJ fp;
  2038     OBJ _handle  = __INST(handle);
  2100 
  2039 
  2101     if ((__INST(handleType) == nil)
  2040     if (_handle != nil) {
  2102      || (__INST(handleType) == @symbol(filePointer))
  2041         if (__INST(handleType) == @symbol(socketHandle)) {
  2103      || (__INST(handleType) == @symbol(socketFilePointer))
  2042             RETURN (_handle);
  2104      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2043         } else if ((__INST(handleType) == nil)
  2105 	if ((fp = __INST(handle)) != nil) {
  2044                      || (__INST(handleType) == @symbol(filePointer))
  2106 	    FILEPOINTER f;
  2045                      || (__INST(handleType) == @symbol(socketFilePointer))
  2107 
  2046                      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2108 	    f = __FILEVal(fp);
  2047             RETURN ( __MKINT(fileno(__FILEVal(_handle))));
  2109 	    RETURN ( __MKINT(fileno(f)) );
  2048         }
  2110 	}
       
  2111     }
  2049     }
  2112 %}.
  2050 %}.
  2113     handle isNil ifTrue:[^ self errorNotOpen].
  2051     handle isNil ifTrue:[^ self errorNotOpen].
  2114     ^ self fileDescriptorOfFile:handle
  2052     ^ self fileDescriptorOfFile:handle
  2115 !
  2053 !
  2126 fileHandle
  2064 fileHandle
  2127     "return the fileHandle of the receiver.
  2065     "return the fileHandle of the receiver.
  2128      Under unix, this is the fileDescriptor; under windows, this is the Handle."
  2066      Under unix, this is the fileDescriptor; under windows, this is the Handle."
  2129 
  2067 
  2130 %{
  2068 %{
  2131     OBJ fp;
  2069     OBJ _handle  = __INST(handle);
  2132 
  2070 
  2133     if ((__INST(handleType) == nil)
  2071     if (_handle != nil) {
  2134      || (__INST(handleType) == @symbol(filePointer))
  2072         if ((__INST(handleType) == @symbol(fileHandle)) 
  2135      || (__INST(handleType) == @symbol(socketFilePointer))
  2073             || (__INST(handleType) == @symbol(socketHandle))) {
  2136      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2074             RETURN (_handle);
  2137 	if ((fp = __INST(handle)) != nil) {
  2075         } else if ((__INST(handleType) == nil)
  2138 	    FILEPOINTER f;
  2076                      || (__INST(handleType) == @symbol(filePointer))
  2139 	    int fd;
  2077                      || (__INST(handleType) == @symbol(socketFilePointer))
  2140 
  2078                      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2141 	    f = __FILEVal(fp);
       
  2142 	    fd = fileno(f);
       
  2143 #ifdef WIN32
  2079 #ifdef WIN32
  2144 	    {
  2080             RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle)))));
  2145 		HANDLE h;
       
  2146 		h = _get_osfhandle(fd);
       
  2147 		RETURN (__MKEXTERNALADDRESS(h));
       
  2148 	    }
       
  2149 #else
  2081 #else
  2150 	    RETURN ( __MKINT(fileno(f)) );
  2082             RETURN (__MKINT(fileno(__FILEVal(_handle))));
  2151 #endif
  2083 #endif
  2152 	}
  2084         }
  2153     }
  2085     }
  2154 #ifdef WIN32
       
  2155     if ((__INST(handleType) == @symbol(fileHandle)) || (__INST(handleType) == @symbol(socketHandle))) {
       
  2156 	RETURN (__INST(handle));
       
  2157     }
       
  2158 #endif
       
  2159 %}.
  2086 %}.
  2160     handle isNil ifTrue:[^ self errorNotOpen].
  2087     handle isNil ifTrue:[^ self errorNotOpen].
  2161     ^ self fileHandleOfFile:handle
  2088     ^ handle
  2162 !
  2089 !
  2163 
  2090 
  2164 filePointer
  2091 filePointer
  2165     "return the filePointer of the receiver -
  2092     "return the filePointer of the receiver -
  2166      notice: for portability stdio is used; this means you will get
  2093      notice: for portability stdio is used; this means you will get
  2173 	^ handle
  2100 	^ handle
  2174     ].
  2101     ].
  2175     ^ self error:'not a FILE*'
  2102     ^ self error:'not a FILE*'
  2176 !
  2103 !
  2177 
  2104 
       
  2105 handleType
       
  2106     ^ handleType
       
  2107 !
       
  2108 
  2178 lineEndCRLF
  2109 lineEndCRLF
  2179     eolMode := #crlf
  2110     eolMode := #crlf
  2180 !
  2111 !
  2181 
  2112 
  2182 lineEndTransparent
  2113 lineEndTransparent
  2227 ! !
  2158 ! !
  2228 
  2159 
  2229 !ExternalStream methodsFor:'closing'!
  2160 !ExternalStream methodsFor:'closing'!
  2230 
  2161 
  2231 close
  2162 close
  2232     "close the stream. 
  2163     "close the stream.
  2233      No error of the stream is not open."
  2164      No error of the stream is not open."
  2234 
  2165 
  2235     self isOpen ifTrue:[
  2166     self isOpen ifTrue:[
  2236         Lobby unregister:self.
  2167 	Lobby unregister:self.
  2237         self closeFile.
  2168 	self closeFile.
  2238     ].
  2169     ].
  2239 !
  2170 !
  2240 
  2171 
  2241 shutDown
  2172 shutDown
  2242     "close the stream - added for protocol compatibility with PipeStream.
  2173     "close the stream - added for protocol compatibility with PipeStream.
  2581 
  2512 
  2582     __INST(lastErrorNumber) = nil;
  2513     __INST(lastErrorNumber) = nil;
  2583     if ((__INST(handleType) == nil)
  2514     if ((__INST(handleType) == nil)
  2584      || (__INST(handleType) == @symbol(filePointer))
  2515      || (__INST(handleType) == @symbol(filePointer))
  2585      || (__INST(handleType) == @symbol(socketFilePointer))
  2516      || (__INST(handleType) == @symbol(socketFilePointer))
       
  2517      || (__INST(handleType) == @symbol(socketHandle))
  2586      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2518      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2587 	if (((fp = __INST(handle)) != nil)
  2519         if (((fp = __INST(handle)) != nil)
  2588 	    && (__INST(mode) != @symbol(writeonly))
  2520             && (__INST(mode) != @symbol(writeonly))
  2589 	    && (__INST(binary) != true)
  2521             && (__INST(binary) != true)
  2590 	) {
  2522         ) {
  2591 	    f = __FILEVal(fp);
  2523             f = __FILEVal(fp);
  2592 	    buffer[0] = '\0';
  2524             buffer[0] = '\0';
  2593 
  2525 
  2594 	    _buffered = (__INST(buffered) == true);
  2526             _buffered = (__INST(buffered) == true);
  2595 	    if (_buffered) {
  2527             if (_buffered) {
  2596 		__READING__(f);
  2528                 __READING__(f);
  2597 	    }
  2529             }
  2598 
  2530 
  2599 	    rslt = nextPtr = buffer;
  2531             rslt = nextPtr = buffer;
  2600 	    limit = buffer + sizeof(buffer) - 2;
  2532             limit = buffer + sizeof(buffer) - 2;
  2601 
  2533 
  2602 	    for (;;) {
  2534             for (;;) {
  2603 		__READBYTE__(ret, f, nextPtr, _buffered, __INST(handleType));
  2535                 __READBYTE__(ret, f, nextPtr, _buffered, __INST(handleType));
  2604 		if (ret <= 0) {
  2536                 if (ret <= 0) {
  2605 		    if (nextPtr == buffer)
  2537                     if (nextPtr == buffer)
  2606 			rslt = NULL;
  2538                         rslt = NULL;
  2607 		    if (ret == 0) {
  2539                     if (ret == 0) {
  2608 			__INST(hitEOF) = true;
  2540                         __INST(hitEOF) = true;
  2609 			break;
  2541                         break;
  2610 		    } else {
  2542                     } else {
  2611 			error = __mkSmallInteger(__threadErrno);
  2543                         error = __mkSmallInteger(__threadErrno);
  2612 			goto err;
  2544                         goto err;
  2613 		    }
  2545                     }
  2614 		}
  2546                 }
  2615 
  2547 
  2616 		if (*nextPtr == '\n') {
  2548                 if (*nextPtr == '\n') {
  2617 		    cutOff = 1;
  2549                     cutOff = 1;
  2618 		    *nextPtr = '\0';
  2550                     *nextPtr = '\0';
  2619 		    break;
  2551                     break;
  2620 		}
  2552                 }
  2621 		if (*nextPtr == '\r') {
  2553                 if (*nextPtr == '\r') {
  2622 		    char peekChar;
  2554                     char peekChar;
  2623 
  2555 
  2624 		    /*
  2556                     /*
  2625 		     * peek ahead for a newLine ...
  2557                      * peek ahead for a newLine ...
  2626 		     */
  2558                      */
  2627 		    __READBYTE__(ret, f, &peekChar, _buffered, __INST(handleType));
  2559                     __READBYTE__(ret, f, &peekChar, _buffered, __INST(handleType));
  2628 		    if (ret <= 0) {
  2560                     if (ret <= 0) {
  2629 			cutOff = 1;
  2561                         cutOff = 1;
  2630 			*nextPtr = '\0';
  2562                         *nextPtr = '\0';
  2631 			if (ret == 0) {
  2563                         if (ret == 0) {
  2632 			    __INST(hitEOF) = true;
  2564                             __INST(hitEOF) = true;
  2633 			    break;
  2565                             break;
  2634 			}
  2566                         }
  2635 			error = __mkSmallInteger(__threadErrno);
  2567                         error = __mkSmallInteger(__threadErrno);
  2636 			goto err;
  2568                         goto err;
  2637 		    }
  2569                     }
  2638 
  2570 
  2639 		    if (peekChar == '\n') {
  2571                     if (peekChar == '\n') {
  2640 			cutOff = 2;
  2572                         cutOff = 2;
  2641 			*nextPtr = '\0';
  2573                         *nextPtr = '\0';
  2642 			break;
  2574                         break;
  2643 		    }
  2575                     }
  2644 
  2576 
  2645 		    __UNGETC__(peekChar, f, _buffered);
  2577                     __UNGETC__(peekChar, f, _buffered);
  2646 
  2578 
  2647 		    cutOff = 1;
  2579                     cutOff = 1;
  2648 		    *nextPtr = '\0';
  2580                     *nextPtr = '\0';
  2649 		    break;
  2581                     break;
  2650 		}
  2582                 }
  2651 
  2583 
  2652 		nextPtr++;
  2584                 nextPtr++;
  2653 		if (nextPtr >= limit) {
  2585                 if (nextPtr >= limit) {
  2654 		    *nextPtr = '\0';
  2586                     *nextPtr = '\0';
  2655 		    lineTooLong = 1;
  2587                     lineTooLong = 1;
  2656 		    if (@global(InfoPrinting) == true) {
  2588                     if (@global(InfoPrinting) == true) {
  2657 			fprintf(stderr, "ExtStream [warning]: line truncated in nextLine\n");
  2589                         fprintf(stderr, "ExtStream [warning]: line truncated in nextLine\n");
  2658 		    }
  2590                     }
  2659 		    break;
  2591                     break;
  2660 		}
  2592                 }
  2661 	    }
  2593             }
  2662 
  2594 
  2663 	    if (rslt != NULL) {
  2595             if (rslt != NULL) {
  2664 		len = nextPtr-buffer;
  2596                 len = nextPtr-buffer;
  2665 
  2597 
  2666 		if (__isSmallInteger(__INST(position))) {
  2598                 if (__isSmallInteger(__INST(position))) {
  2667 		    INT np = __intVal(__INST(position)) + len + cutOff;
  2599                     INT np = __intVal(__INST(position)) + len + cutOff;
  2668 		    OBJ t;
  2600                     OBJ t;
  2669 
  2601 
  2670 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  2602                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  2671 		} else {
  2603                 } else {
  2672 		    __INST(position) = nil; /* i.e. do not know */
  2604                     __INST(position) = nil; /* i.e. do not know */
  2673 		}
  2605                 }
  2674 		/* remove any EOL character */
  2606                 /* remove any EOL character */
  2675 		if (len != 0) {
  2607                 if (len != 0) {
  2676 		    if (buffer[len-1] == '\n') {
  2608                     if (buffer[len-1] == '\n') {
  2677 			buffer[--len] = '\0';
  2609                         buffer[--len] = '\0';
  2678 		    }
  2610                     }
  2679 		    if ((len != 0) && (buffer[len-1] == '\r')) {
  2611                     if ((len != 0) && (buffer[len-1] == '\r')) {
  2680 			buffer[--len] = '\0';
  2612                         buffer[--len] = '\0';
  2681 		    }
  2613                     }
  2682 		}
  2614                 }
  2683 		line = __MKSTRING_L(buffer, len);
  2615                 line = __MKSTRING_L(buffer, len);
  2684 		if (! lineTooLong) {
  2616                 if (! lineTooLong) {
  2685 		    RETURN ( line );
  2617                     RETURN ( line );
  2686 		}
  2618                 }
  2687 	    }
  2619             }
  2688 	}
  2620         }
  2689     }
  2621     }
  2690 err: ;
  2622 err: ;
  2691 %}.
  2623 %}.
  2692     line notNil ifTrue:[
  2624     line notNil ifTrue:[
  2693 	"/ the line as read is longer than 32k characters (boy - what a line)
  2625         "/ the line as read is longer than 32k characters (boy - what a line)
  2694 	"/ The exception could be handled by reading more and returning the
  2626         "/ The exception could be handled by reading more and returning the
  2695 	"/ concatenation in your exception handler (the receiver and the partial
  2627         "/ concatenation in your exception handler (the receiver and the partial
  2696 	"/ line are passed as parameter)
  2628         "/ line are passed as parameter)
  2697 
  2629 
  2698 	LineTooLongErrorSignal isHandled ifTrue:[
  2630         LineTooLongErrorSignal isHandled ifTrue:[
  2699 	    ^ LineTooLongErrorSignal
  2631             ^ LineTooLongErrorSignal
  2700 		raiseRequestWith:(Array with:self with:line)
  2632                 raiseRequestWith:(Array with:self with:line)
  2701 		     errorString:('line too long read error')
  2633                      errorString:('line too long read error')
  2702 	].
  2634         ].
  2703 	^ line , self nextLine
  2635         ^ line , self nextLine
  2704     ].
  2636     ].
  2705 
  2637 
  2706     (hitEOF == true) ifTrue:[^ self pastEndRead].
  2638     (hitEOF == true) ifTrue:[^ self pastEndRead].
  2707     error notNil ifTrue:[
  2639     error notNil ifTrue:[
  2708 	lastErrorNumber := error.
  2640         lastErrorNumber := error.
  2709 	^ self readError:error
  2641         ^ self readError:error
  2710     ].
  2642     ].
  2711     handle isNil ifTrue:[^ self errorNotOpen].
  2643     handle isNil ifTrue:[^ self errorNotOpen].
  2712     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  2644     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  2713     (binary == true) ifTrue:[^ self errorBinary].
  2645     (binary == true) ifTrue:[^ self errorBinary].
  2714     ^ super nextLine
  2646     ^ super nextLine
  2728 
  2660 
  2729     __INST(lastErrorNumber) = nil;
  2661     __INST(lastErrorNumber) = nil;
  2730     if ((__INST(handleType) == nil)
  2662     if ((__INST(handleType) == nil)
  2731      || (__INST(handleType) == @symbol(filePointer))
  2663      || (__INST(handleType) == @symbol(filePointer))
  2732      || (__INST(handleType) == @symbol(socketFilePointer))
  2664      || (__INST(handleType) == @symbol(socketFilePointer))
       
  2665      || (__INST(handleType) == @symbol(socketHandle))
  2733      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2666      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2734 	if (((fp = __INST(handle)) != nil)
  2667         if (((fp = __INST(handle)) != nil)
  2735 	    && (__INST(mode) != @symbol(readonly))
  2668             && (__INST(mode) != @symbol(readonly))
  2736 	    && (__INST(binary) != true)
  2669             && (__INST(binary) != true)
  2737 	    && __isStringLike(aString)
  2670             && __isStringLike(aString)
  2738 	) {
  2671         ) {
  2739 	    f = __FILEVal(fp);
  2672             f = __FILEVal(fp);
  2740 	    len = __stringSize(aString);
  2673             len = __stringSize(aString);
  2741 
  2674 
  2742 	    if (_buffered = (__INST(buffered) == true)) {
  2675             if (_buffered = (__INST(buffered) == true)) {
  2743 		__WRITING__(f)
  2676                 __WRITING__(f)
  2744 	    }
  2677             }
  2745 #ifdef WIN32
  2678 #ifdef WIN32
  2746 	    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  2679             if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  2747 		cnt = __win32_fwrite(__stringVal(aString), 1, len, f);
  2680                 cnt = __win32_fwrite(__stringVal(aString), 1, len, f);
  2748 	    } else
  2681             } else
  2749 #endif
  2682 #endif
  2750 	    {
  2683             {
  2751 		o_offs = (char *)__stringVal(aString)-(char *)aString;
  2684                 o_offs = (char *)__stringVal(aString)-(char *)aString;
  2752 		__WRITEBYTES_OBJ__(cnt, f, aString, o_offs, len, _buffered, __INST(handleType));
  2685                 __WRITEBYTES_OBJ__(cnt, f, aString, o_offs, len, _buffered, __INST(handleType));
  2753 	    }
  2686             }
  2754 	    if (cnt == len) {
  2687             if (cnt == len) {
  2755 		OBJ mode = __INST(eolMode);
  2688                 OBJ mode = __INST(eolMode);
  2756 
  2689 
  2757 		len1 = len;
  2690                 len1 = len;
  2758 
  2691 
  2759 		if (mode == @symbol(cr)) {
  2692                 if (mode == @symbol(cr)) {
  2760 		    cp = "\r"; len = 1;
  2693                     cp = "\r"; len = 1;
  2761 		} else if (mode == @symbol(crlf)) {
  2694                 } else if (mode == @symbol(crlf)) {
  2762 		    cp = "\r\n"; len = 2;
  2695                     cp = "\r\n"; len = 2;
  2763 		} else {
  2696                 } else {
  2764 		    cp = "\n"; len = 1;
  2697                     cp = "\n"; len = 1;
  2765 		}
  2698                 }
  2766 #ifdef WIN32
  2699 #ifdef WIN32
  2767 		if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  2700                 if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  2768 		    cnt = __win32_fwrite(cp, 1, len, f);
  2701                     cnt = __win32_fwrite(cp, 1, len, f);
  2769 		} else
  2702                 } else
  2770 #endif
  2703 #endif
  2771 		{
  2704                 {
  2772 		    __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType));
  2705                     __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType));
  2773 		}
  2706                 }
  2774 		if (cnt > 0) {
  2707                 if (cnt > 0) {
  2775 		    if (__isSmallInteger(__INST(position))) {
  2708                     if (__isSmallInteger(__INST(position))) {
  2776 			INT np = __intVal(__INST(position)) + cnt;
  2709                         INT np = __intVal(__INST(position)) + cnt;
  2777 			OBJ t;
  2710                         OBJ t;
  2778 
  2711 
  2779 			t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  2712                         t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  2780 		    } else {
  2713                     } else {
  2781 			__INST(position) = nil; /* i.e. do not know */
  2714                         __INST(position) = nil; /* i.e. do not know */
  2782 		    }
  2715                     }
  2783 		    RETURN ( self );
  2716                     RETURN ( self );
  2784 		}
  2717                 }
  2785 	    }
  2718             }
  2786 	    error = __mkSmallInteger(__threadErrno);
  2719             error = __mkSmallInteger(__threadErrno);
  2787 	}
  2720         }
  2788     }
  2721     }
  2789 %}.
  2722 %}.
  2790     error notNil ifTrue:[
  2723     error notNil ifTrue:[
  2791 	lastErrorNumber := error.
  2724         lastErrorNumber := error.
  2792 	self writeError:error.
  2725         self writeError:error.
  2793 	^ self
  2726         ^ self
  2794     ].
  2727     ].
  2795     super nextPutLine:aString.
  2728     super nextPutLine:aString.
  2796 !
  2729 !
  2797 
  2730 
  2798 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil
  2731 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil
  2975      a pointer to the data is passed.
  2908      a pointer to the data is passed.
  2976      This allows performing most ioctls
  2909      This allows performing most ioctls
  2977      - however, it might be tricky to setup the buffer.
  2910      - however, it might be tricky to setup the buffer.
  2978      Be careful in what you pass - ST/X cannot validate its correctness."
  2911      Be careful in what you pass - ST/X cannot validate its correctness."
  2979 
  2912 
       
  2913     |error|
       
  2914 
  2980 %{
  2915 %{
  2981 #if !defined(MSDOS_LIKE) && !defined(__openVMS__)
  2916 #if !defined(MSDOS_LIKE) && !defined(__openVMS__)
  2982     FILEPOINTER f;
  2917     int fd;
  2983     int ret;
  2918     int ret;
  2984     unsigned int ioNum;
  2919     unsigned int ioNum;
  2985     OBJ fp;
       
  2986     INT ioArg;
  2920     INT ioArg;
  2987 
  2921     OBJ fp = __INST(handle);
  2988     __INST(lastErrorNumber) = nil;
  2922 
  2989     if ((__INST(handleType) == nil)
  2923     if (fp == nil)
  2990      || (__INST(handleType) == @symbol(filePointer))
  2924         goto out;
  2991      || (__INST(handleType) == @symbol(socketFilePointer))
  2925 
  2992      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  2926     if (!__isInteger(ioctlNumber)
  2993 	if ((fp = __INST(handle)) != nil) {
  2927          || (!__isInteger(arg)
  2994 	    if (__isInteger(ioctlNumber)
  2928              && (arg != nil)
  2995 	     && (__isInteger(arg)
  2929              && !__isBytes(arg)
  2996 		 || (arg == nil)
  2930              && !__isExternalBytesLike(arg)
  2997 		 || __isBytes(arg)
  2931              && !__isExternalAddress(arg))) {
  2998 		 || __isExternalBytesLike(arg)
  2932         error = @symbol(badArgument);
  2999 		 || __isExternalAddress(arg))) {
  2933         goto out;
  3000 		f = __FILEVal(fp);
       
  3001 		ioNum = __unsignedLongIntVal(ioctlNumber);
       
  3002 
       
  3003 		__BEGIN_INTERRUPTABLE__
       
  3004 		do {
       
  3005 		    __threadErrno = 0;
       
  3006 		    if (arg == nil) {
       
  3007 			ioArg = 0;
       
  3008 		    } else if (__isSmallInteger(arg)) {
       
  3009 			ioArg = __intVal(arg);
       
  3010 		    } else if (__isInteger(arg)) {
       
  3011 			ioArg = __unsignedLongIntVal(arg);
       
  3012 		    } else if (__isExternalBytesLike(arg)) {
       
  3013 			ioArg = (INT)(__externalBytesAddress(arg));
       
  3014 		    } else if (__isExternalAddress(arg)) {
       
  3015 			ioArg = (INT)(__externalAddressVal(arg));
       
  3016 		    } else {
       
  3017 			ioArg = (INT)(__ByteArrayInstPtr(arg)->ba_element);
       
  3018 		    }
       
  3019 		    ret = ioctl(fileno(f), ioNum, ioArg);
       
  3020 		} while (ret < 0 && __threadErrno == EINTR);
       
  3021 		__END_INTERRUPTABLE__
       
  3022 
       
  3023 		if (ret >= 0) {
       
  3024 		    RETURN ( __mkSmallInteger(ret) );
       
  3025 		}
       
  3026 		__INST(position) = nil; /* i.e. do not know */
       
  3027 		__INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
       
  3028 	    }
       
  3029 	}
       
  3030     }
  2934     }
       
  2935 
       
  2936     if (__INST(handleType) == @symbol(socketHandle)) {
       
  2937         fd = __FILEVal(fp);
       
  2938     } else if ((__INST(handleType) == nil)
       
  2939          || (__INST(handleType) == @symbol(filePointer))
       
  2940          || (__INST(handleType) == @symbol(socketFilePointer))
       
  2941          || (__INST(handleType) == @symbol(pipeFilePointer))) {
       
  2942         fd = fileno(__FILEVal(fp));
       
  2943     } else {
       
  2944         error = @symbol(badHandleType);
       
  2945         goto out;
       
  2946     }
       
  2947     
       
  2948     ioNum = __unsignedLongIntVal(ioctlNumber);
       
  2949 
       
  2950     __BEGIN_INTERRUPTABLE__
       
  2951     do {
       
  2952         __threadErrno = 0;
       
  2953         if (arg == nil) {
       
  2954             ioArg = 0;
       
  2955         } else if (__isSmallInteger(arg)) {
       
  2956             ioArg = __intVal(arg);
       
  2957         } else if (__isInteger(arg)) {
       
  2958             ioArg = __unsignedLongIntVal(arg);
       
  2959         } else if (__isExternalBytesLike(arg)) {
       
  2960             ioArg = (INT)(__externalBytesAddress(arg));
       
  2961         } else if (__isExternalAddress(arg)) {
       
  2962             ioArg = (INT)(__externalAddressVal(arg));
       
  2963         } else {
       
  2964             ioArg = (INT)(__ByteArrayInstPtr(arg)->ba_element);
       
  2965         }
       
  2966         ret = ioctl(fd, ioNum, ioArg);
       
  2967     } while (ret < 0 && __threadErrno == EINTR);
       
  2968     __END_INTERRUPTABLE__
       
  2969 
       
  2970     if (ret >= 0) {
       
  2971         RETURN ( __mkSmallInteger(ret) );
       
  2972     }
       
  2973     error = __mkSmallInteger(__threadErrno);
  3031 #endif
  2974 #endif
       
  2975 
       
  2976 out:;
  3032 %}.
  2977 %}.
  3033     lastErrorNumber notNil ifTrue:[^ self ioError].
  2978     error notNil ifTrue:[
       
  2979         lastErrorNumber := error.
       
  2980         ^ self ioError:error.
       
  2981     ].
  3034     handle isNil ifTrue:[^ self errorNotOpen].
  2982     handle isNil ifTrue:[^ self errorNotOpen].
  3035     "
  2983 
  3036      argument is not an integer
  2984     "/ the system does not support ioctl (MSDOS or VMS)
  3037     "
       
  3038     (ioctlNumber isMemberOf:SmallInteger) ifFalse:[^ self primitiveFailed].
       
  3039     "
       
  3040      the system does not support ioctl (MSDOS or VMS)
       
  3041     "
       
  3042     ^ self errorUnsupportedOperation
  2985     ^ self errorUnsupportedOperation
  3043 !
  2986 !
  3044 
  2987 
  3045 reset
  2988 reset
  3046     "set the read position to the beginning of the collection"
  2989     "set the read position to the beginning of the collection"
  3061 
  3004 
  3062     self flush.
  3005     self flush.
  3063 
  3006 
  3064 %{
  3007 %{
  3065 #if !defined(__openVMS__)
  3008 #if !defined(__openVMS__)
  3066     FILEPOINTER f;
  3009     int fd;
  3067     int ret;
  3010     int ret;
  3068     OBJ fp;
  3011     OBJ fp = __INST(handle);
  3069 
  3012 
  3070     __INST(lastErrorNumber) = nil;
  3013     if (fp == nil)
  3071     if ((__INST(handleType) == nil)
  3014         goto out;
  3072      || (__INST(handleType) == @symbol(filePointer))
  3015 
  3073      || (__INST(handleType) == @symbol(socketFilePointer))
  3016     if (__INST(handleType) == @symbol(socketHandle)) {
  3074      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3017         fd = __FILEVal(fp);
  3075 	if ((fp = __INST(handle)) != nil) {
  3018     } else if ((__INST(handleType) == nil)
  3076 	    f = __FILEVal(fp);
  3019                || (__INST(handleType) == @symbol(filePointer))
       
  3020                || (__INST(handleType) == @symbol(socketFilePointer))
       
  3021                || (__INST(handleType) == @symbol(pipeFilePointer))) {
       
  3022         fd = fileno(__FILEVal(fp));
       
  3023     } else {
       
  3024         error = @symbol(badHandleType);
       
  3025         goto out;
       
  3026     }
       
  3027         
  3077 #ifdef WIN32
  3028 #ifdef WIN32
  3078 	    __threadErrno = 0;
  3029      __threadErrno = 0;
  3079 	    ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fileno(f)));
  3030      ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fd));
  3080 	    if (ret) {
  3031      if (ret) {
  3081 		RETURN (self);
  3032          RETURN (self);
  3082 	    }
  3033      }
  3083 #else
  3034 #else
  3084 
  3035      __BEGIN_INTERRUPTABLE__
  3085 	    __BEGIN_INTERRUPTABLE__
  3036      do {
  3086 	    do {
  3037          ret = fsync(fd);
  3087 		ret = fsync(fileno(f));
  3038      } while ((ret < 0) && (__threadErrno == EINTR));
  3088 	    } while ((ret < 0) && (__threadErrno == EINTR));
  3039      __END_INTERRUPTABLE__
  3089 	    __END_INTERRUPTABLE__
  3040 
  3090 
  3041      if (ret >= 0) {
  3091 	    if (ret >= 0) {
  3042          RETURN (self);
  3092 		RETURN (self);
  3043      }
  3093 	    }
       
  3094 #endif /* ! WIN32 */
  3044 #endif /* ! WIN32 */
  3095 	    error = __mkSmallInteger(__threadErrno);
  3045      error = __mkSmallInteger(__threadErrno);
  3096 	}
       
  3097     }
       
  3098 #endif /* ! __openVMS__ */
  3046 #endif /* ! __openVMS__ */
       
  3047 out:;
  3099 %}.
  3048 %}.
  3100     error notNil ifTrue:[
  3049     error notNil ifTrue:[
  3101 	lastErrorNumber := error.
  3050         lastErrorNumber := error.
  3102 	self ioError:error.
  3051         self ioError:error.
  3103 	^ self.
  3052         ^ self.
  3104     ].
  3053     ].
  3105     handle isNil ifTrue:[self errorNotOpen].
  3054     handle isNil ifTrue:[self errorNotOpen].
  3106 
  3055 
  3107     "
  3056     "
  3108 	|f|
  3057         |f|
  3109 	f := 'x' asFilename writeStream.
  3058         f := 'x' asFilename writeStream.
  3110 	f nextPutAll:'hallo'; sync; syncData; close
  3059         f nextPutAll:'hallo'; sync; syncData; close
  3111     "
  3060     "
  3112 !
  3061 !
  3113 
  3062 
  3114 syncData
  3063 syncData
  3115     "make sure, that the OS writes cached data to the disk.
  3064     "make sure, that the OS writes cached data to the disk.
  3116      In this case, metadata is only written, if it is
  3065      In this case, metadata is only written, if it is
  3117      required to read the file's data (so metadata will not be written,
  3066      required to read the file's data (so metadata will not be written,
  3118      if only access/modification time has changed)."
  3067      if only access/modification time has changed)."
  3119 
       
  3120     |error|
  3068     |error|
  3121 
  3069 
  3122     self flush.
  3070     self flush.
  3123 
  3071 
  3124 %{
  3072 %{
  3125 #if defined(HAS_FDATASYNC)
  3073 #if !defined(__openVMS__)
       
  3074     int fd;
  3126     int ret;
  3075     int ret;
  3127 
  3076     OBJ fp = __INST(handle);
  3128     __INST(lastErrorNumber) = nil;
  3077 
  3129     if ((__INST(handleType) == nil)
  3078     if (fp == nil)
  3130      || (__INST(handleType) == @symbol(filePointer))
  3079         goto out;
  3131      || (__INST(handleType) == @symbol(socketFilePointer))
  3080 
  3132      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3081     if (__INST(handleType) == @symbol(socketHandle)) {
  3133 	OBJ fp;
  3082         fd = __FILEVal(fp);
  3134 	FILEPOINTER f;
  3083     } else if ((__INST(handleType) == nil)
  3135 
  3084                || (__INST(handleType) == @symbol(filePointer))
  3136 	if ((fp = __INST(handle)) != nil) {
  3085                || (__INST(handleType) == @symbol(socketFilePointer))
  3137 	    f = __FILEVal(fp);
  3086                || (__INST(handleType) == @symbol(pipeFilePointer))) {
       
  3087         fd = fileno(__FILEVal(fp));
       
  3088     } else {
       
  3089         error = @symbol(badHandleType);
       
  3090         goto out;
       
  3091     }
       
  3092 
  3138 #ifdef WIN32
  3093 #ifdef WIN32
  3139 	    __threadErrno = 0;
  3094      __threadErrno = 0;
  3140 	    ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fileno(f)));
  3095      ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fd));
  3141 	    if (ret) {
  3096      if (ret) {
  3142 		RETURN (self);
  3097          RETURN (self);
  3143 	    }
  3098      }
  3144 #else
  3099 #else
  3145 
  3100      __BEGIN_INTERRUPTABLE__
  3146 	    __BEGIN_INTERRUPTABLE__
  3101      do {
  3147 	    do {
  3102          ret = fdatasync(fd);
  3148 		ret = fdatasync(fileno(f));
  3103      } while ((ret < 0) && (__threadErrno == EINTR));
  3149 	    } while ((ret < 0) && (__threadErrno == EINTR));
  3104      __END_INTERRUPTABLE__
  3150 	    __END_INTERRUPTABLE__
  3105 
  3151 
  3106      if (ret >= 0) {
  3152 	    if (ret >= 0) {
  3107          RETURN (self);
  3153 		RETURN (self);
  3108      }
  3154 	    }
       
  3155 #endif /* ! WIN32 */
  3109 #endif /* ! WIN32 */
  3156 	    error = __mkSmallInteger(__threadErrno);
  3110      error = __mkSmallInteger(__threadErrno);
  3157 	}
       
  3158     }
       
  3159 #endif /* ! __openVMS__ */
  3111 #endif /* ! __openVMS__ */
       
  3112 out:;
  3160 %}.
  3113 %}.
       
  3114 
  3161     error notNil ifTrue:[
  3115     error notNil ifTrue:[
  3162 	lastErrorNumber := error.
  3116         lastErrorNumber := error.
  3163 	self ioError:error.
  3117         self ioError:error.
  3164 	^ self.
  3118         ^ self.
  3165     ].
  3119     ].
  3166     handle isNil ifTrue:[^ self errorNotOpen].
  3120     handle isNil ifTrue:[^ self errorNotOpen].
  3167 
  3121 
  3168     "if notdef HAS_DATASYNC, fall back"
  3122     "if notdef HAS_DATASYNC, fall back"
  3169     self sync.
  3123     self sync.
  3170 
  3124 
  3171     "
  3125     "
  3172 	|f|
  3126         |f|
  3173 	f := 'x' asFilename writeStream.
  3127         f := 'x' asFilename writeStream.
  3174 	f nextPutAll:'hallo'; sync; syncData; close
  3128         f nextPutAll:'hallo'; sync; syncData; close
  3175     "
       
  3176 !
       
  3177 
       
  3178 truncateTo:newSize
       
  3179     "truncate the underlying OS file to newSize.
       
  3180      Warning: this may not be implemented on all platforms."
       
  3181 
       
  3182 %{
       
  3183 #ifdef HAS_FTRUNCATE
       
  3184     FILEPOINTER f;
       
  3185     OBJ fp;
       
  3186     off_t truncateSize;
       
  3187 
       
  3188     if ((__INST(handleType) == nil)
       
  3189      || (__INST(handleType) == @symbol(filePointer))
       
  3190      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3191      || (__INST(handleType) == @symbol(pipeFilePointer))) {
       
  3192 	if (((fp = __INST(handle)) != nil)
       
  3193 	    && (__INST(mode) != @symbol(readonly))) {
       
  3194 	    if (__isSmallInteger(newSize)) {
       
  3195 		truncateSize = __intVal(newSize);
       
  3196 		if (truncateSize < 0) {
       
  3197 		    goto getOutOfHere;
       
  3198 		}
       
  3199 	    } else {
       
  3200 		truncateSize = __signedLongIntVal(newSize);
       
  3201 		if (truncateSize < 0) {
       
  3202 		    goto getOutOfHere;
       
  3203 		}
       
  3204 		if (truncateSize == 0) {
       
  3205 		    if (sizeof(truncateSize) == 8) {
       
  3206 			if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
       
  3207 			    goto getOutOfHere;
       
  3208 			}
       
  3209 		    } else {
       
  3210 			goto getOutOfHere;
       
  3211 		    }
       
  3212 		}
       
  3213 	    }
       
  3214 
       
  3215 	    f = __FILEVal(fp);
       
  3216 
       
  3217 	    if (__INST(buffered) == true) {
       
  3218 		__READING__(f)
       
  3219 #ifdef WIN32
       
  3220 		if ((dst == __win32_stdout()) || (dst == __win32_stderr())) {
       
  3221 		    win32_fflush(f);
       
  3222 		} else
       
  3223 #endif
       
  3224 		{
       
  3225 		    FFLUSH(f);
       
  3226 		}
       
  3227 		OPT_FSEEK(f, 0L, SEEK_END); /* needed in stdio */
       
  3228 	    }
       
  3229 	    ftruncate(fileno(f), truncateSize);
       
  3230 	    RETURN (self);
       
  3231 	}
       
  3232     }
       
  3233 getOutOfHere: ;
       
  3234 #endif
       
  3235 %}.
       
  3236     handle isNil ifTrue:[self errorNotOpen. ^ self].
       
  3237     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
       
  3238     newSize < 0 ifTrue:[
       
  3239 	self error:'wrong arg'.
       
  3240     ].
       
  3241     self errorUnsupportedOperation
       
  3242 
       
  3243     "
       
  3244      |s|
       
  3245 
       
  3246      s := 'test' asFilename writeStream.
       
  3247      s next:1000 put:$a.
       
  3248      s truncateTo:100.
       
  3249      s close.
       
  3250 
       
  3251      ('test' asFilename fileSize) printNL
       
  3252     "
  3129     "
  3253 ! !
  3130 ! !
  3254 
  3131 
  3255 !ExternalStream methodsFor:'non homogenous reading'!
  3132 !ExternalStream methodsFor:'non homogenous reading'!
  3256 
  3133 
  3338      Use with care - non object oriented I/O.
  3215      Use with care - non object oriented I/O.
  3339      Warning: in general, you cannot use this method to pass data from other
  3216      Warning: in general, you cannot use this method to pass data from other
  3340      architectures since it does not care for byte order or float representation."
  3217      architectures since it does not care for byte order or float representation."
  3341 
  3218 
  3342     |error|
  3219     |error|
       
  3220 
  3343 %{
  3221 %{
  3344     FILEPOINTER f;
  3222     FILEPOINTER f;
  3345     int cnt, offs, ret, _buffered;
  3223     int cnt, offs, ret, _buffered;
  3346     int objSize, nInstBytes;
  3224     int objSize, nInstBytes;
  3347     char *cp;
  3225     char *cp;
  3351 
  3229 
  3352     __INST(lastErrorNumber) = nil;
  3230     __INST(lastErrorNumber) = nil;
  3353     if ((__INST(handleType) == nil)
  3231     if ((__INST(handleType) == nil)
  3354      || (__INST(handleType) == @symbol(filePointer))
  3232      || (__INST(handleType) == @symbol(filePointer))
  3355      || (__INST(handleType) == @symbol(socketFilePointer))
  3233      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3234      || (__INST(handleType) == @symbol(socketHandle))
  3356      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3235      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3357 	if (((fp = __INST(handle)) != nil)
  3236         if (((fp = __INST(handle)) != nil)
  3358 	    && (__INST(mode) != @symbol(writeonly))
  3237             && (__INST(mode) != @symbol(writeonly))
  3359 	    && __bothSmallInteger(count, start)
  3238             && __bothSmallInteger(count, start)
  3360 	) {
  3239         ) {
  3361 	    f = __FILEVal(fp);
  3240             f = __FILEVal(fp);
  3362 
  3241 
  3363 	    cnt = __intVal(count);
  3242             cnt = __intVal(count);
  3364 	    offs = __intVal(start) - 1;
  3243             offs = __intVal(start) - 1;
  3365 
  3244 
  3366 	    if (__isExternalBytesLike(anObject)) {
  3245             if (__isExternalBytesLike(anObject)) {
  3367 		OBJ sz;
  3246                 OBJ sz;
  3368 
  3247 
  3369 		nInstBytes = 0;
  3248                 nInstBytes = 0;
  3370 		extPtr = (char *)(__externalBytesAddress(anObject));
  3249                 extPtr = (char *)(__externalBytesAddress(anObject));
  3371 		if (extPtr == NULL) goto bad;
  3250                 if (extPtr == NULL) goto bad;
  3372 		sz = __externalBytesSize(anObject);
  3251                 sz = __externalBytesSize(anObject);
  3373 		if (__isSmallInteger(sz)) {
  3252                 if (__isSmallInteger(sz)) {
  3374 		    objSize = __intVal(sz);
  3253                     objSize = __intVal(sz);
  3375 		} else {
  3254                 } else {
  3376 		    objSize = 0; /* unknown */
  3255                     objSize = 0; /* unknown */
  3377 		}
  3256                 }
  3378 	    } else {
  3257             } else {
  3379 		OBJ oClass = __Class(anObject);
  3258                 OBJ oClass = __Class(anObject);
  3380 		int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3259                 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3381 
  3260 
  3382 		nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3261                 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3383 
  3262 
  3384 		switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3263                 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3385 		    case BYTEARRAY:
  3264                     case BYTEARRAY:
  3386 		    case WORDARRAY:
  3265                     case WORDARRAY:
  3387 		    case LONGARRAY:
  3266                     case LONGARRAY:
  3388 		    case SWORDARRAY:
  3267                     case SWORDARRAY:
  3389 		    case SLONGARRAY:
  3268                     case SLONGARRAY:
  3390 		    case FLOATARRAY:
  3269                     case FLOATARRAY:
  3391 			break;
  3270                         break;
  3392 		    case DOUBLEARRAY:
  3271                     case DOUBLEARRAY:
  3393 #ifdef __NEED_DOUBLE_ALIGN
  3272 #ifdef __NEED_DOUBLE_ALIGN
  3394 			nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3273                         nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3395 #endif
  3274 #endif
  3396 			break;
  3275                         break;
  3397 		    case LONGLONGARRAY:
  3276                     case LONGLONGARRAY:
  3398 		    case SLONGLONGARRAY:
  3277                     case SLONGLONGARRAY:
  3399 #ifdef __NEED_LONGLONG_ALIGN
  3278 #ifdef __NEED_LONGLONG_ALIGN
  3400 			nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3279                         nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3401 #endif
  3280 #endif
  3402 			break;
  3281                         break;
  3403 		    default:
  3282                     default:
  3404 			goto bad;
  3283                         goto bad;
  3405 		}
  3284                 }
  3406 		extPtr = (char *)0;
  3285                 extPtr = (char *)0;
  3407 		objSize = __Size(anObject) - nInstBytes;
  3286                 objSize = __Size(anObject) - nInstBytes;
  3408 	    }
  3287             }
  3409 
  3288 
  3410 	    if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3289             if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3411 		_buffered = (__INST(buffered) == true);
  3290                 _buffered = (__INST(buffered) == true);
  3412 		if (_buffered) {
  3291                 if (_buffered) {
  3413 		    __READING__(f);
  3292                     __READING__(f);
  3414 		}
  3293                 }
  3415 
  3294 
  3416 		if (extPtr) {
  3295                 if (extPtr) {
  3417 		    __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3296                     __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3418 		} else {
  3297                 } else {
  3419 		    /*
  3298                     /*
  3420 		     * on interrupt, anObject may be moved to another location.
  3299                      * on interrupt, anObject may be moved to another location.
  3421 		     * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__,
  3300                      * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__,
  3422 		     * to get a new address.
  3301                      * to get a new address.
  3423 		     */
  3302                      */
  3424 		    offs += nInstBytes;
  3303                     offs += nInstBytes;
  3425 		    __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3304                     __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3426 		}
  3305                 }
  3427 		/* 0 is NOT an EOF condition here ... */
  3306                 /* 0 is NOT an EOF condition here ... */
  3428 		if (ret >= 0) {
  3307                 if (ret >= 0) {
  3429 		    if (__isSmallInteger(__INST(position))) {
  3308                     if (__isSmallInteger(__INST(position))) {
  3430 			INT np = __intVal(__INST(position)) + ret;
  3309                         INT np = __intVal(__INST(position)) + ret;
  3431 			OBJ t;
  3310                         OBJ t;
  3432 
  3311 
  3433 			t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3312                         t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3434 		    } else {
  3313                     } else {
  3435 			__INST(position) = nil; /* i.e. do not know */
  3314                         __INST(position) = nil; /* i.e. do not know */
  3436 		    }
  3315                     }
  3437 		    RETURN (__mkSmallInteger(ret));
  3316                     RETURN (__mkSmallInteger(ret));
  3438 		}
  3317                 }
  3439 		__INST(position) = nil;
  3318                 __INST(position) = nil;
  3440 		error = __mkSmallInteger(__threadErrno);
  3319                 error = __mkSmallInteger(__threadErrno);
  3441 	    }
  3320             }
  3442 	}
  3321         }
  3443     }
  3322     }
  3444 bad: ;
  3323 bad: ;
  3445 %}.
  3324 %}.
  3446     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3325     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3447     error notNil ifTrue:[
  3326     error notNil ifTrue:[
  3448 	lastErrorNumber := error.
  3327         lastErrorNumber := error.
  3449 	^ self readError:error
  3328         ^ self readError:error
  3450     ].
  3329     ].
  3451     handle isNil ifTrue:[^ self errorNotOpen].
  3330     handle isNil ifTrue:[^ self errorNotOpen].
  3452     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3331     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3453     "
  3332     "
  3454      count not integer or arg not bit-like (String, ByteArray etc)
  3333      count not integer or arg not bit-like (String, ByteArray etc)
  3470 
  3349 
  3471     __INST(lastErrorNumber) = nil;
  3350     __INST(lastErrorNumber) = nil;
  3472     if ((__INST(handleType) == nil)
  3351     if ((__INST(handleType) == nil)
  3473      || (__INST(handleType) == @symbol(filePointer))
  3352      || (__INST(handleType) == @symbol(filePointer))
  3474      || (__INST(handleType) == @symbol(socketFilePointer))
  3353      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3354      || (__INST(handleType) == @symbol(socketHandle))
  3475      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3355      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3476 	if (((fp = __INST(handle)) != nil)
  3356         if (((fp = __INST(handle)) != nil)
  3477 	 && (__INST(mode) != @symbol(writeonly))) {
  3357          && (__INST(mode) != @symbol(writeonly))) {
  3478 	    f = __FILEVal(fp);
  3358             f = __FILEVal(fp);
  3479 
  3359 
  3480 	    _buffered = (__INST(buffered) == true);
  3360             _buffered = (__INST(buffered) == true);
  3481 	    if (_buffered) {
  3361             if (_buffered) {
  3482 		__READING__(f)
  3362                 __READING__(f)
  3483 	    }
  3363             }
  3484 	    __READBYTE__(ret, f, &byte, _buffered, __INST(handleType));
  3364             __READBYTE__(ret, f, &byte, _buffered, __INST(handleType));
  3485 	    if (ret > 0) {
  3365             if (ret > 0) {
  3486 		if (__isSmallInteger(__INST(position))) {
  3366                 if (__isSmallInteger(__INST(position))) {
  3487 		    INT np = __intVal(__INST(position)) + 1;
  3367                     INT np = __intVal(__INST(position)) + 1;
  3488 		    OBJ t;
  3368                     OBJ t;
  3489 
  3369 
  3490 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3370                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3491 		} else {
  3371                 } else {
  3492 		    __INST(position) = nil; /* i.e. do not know */
  3372                     __INST(position) = nil; /* i.e. do not know */
  3493 		}
  3373                 }
  3494 		RETURN (__mkSmallInteger(byte));
  3374                 RETURN (__mkSmallInteger(byte));
  3495 	    }
  3375             }
  3496 
  3376 
  3497 	    if (ret == 0) {
  3377             if (ret == 0) {
  3498 		__INST(hitEOF) = true;
  3378                 __INST(hitEOF) = true;
  3499 	    } else /* ret < 0 */ {
  3379             } else /* ret < 0 */ {
  3500 		__INST(position) = nil;
  3380                 __INST(position) = nil;
  3501 		error = __mkSmallInteger(__threadErrno);
  3381                 error = __mkSmallInteger(__threadErrno);
  3502 	    }
  3382             }
  3503 	}
  3383         }
  3504     }
  3384     }
  3505 %}.
  3385 %}.
  3506     hitEOF ifTrue:[^ self pastEndRead].
  3386     hitEOF ifTrue:[^ self pastEndRead].
  3507     error notNil ifTrue:[
  3387     error notNil ifTrue:[
  3508 	lastErrorNumber := error.
  3388         lastErrorNumber := error.
  3509 	^ self readError:error
  3389         ^ self readError:error
  3510     ].
  3390     ].
  3511     handle isNil ifTrue:[^ self errorNotOpen].
  3391     handle isNil ifTrue:[^ self errorNotOpen].
  3512     ^ self errorWriteOnly
  3392     ^ self errorWriteOnly
  3513 !
  3393 !
  3514 
  3394 
  3547 
  3427 
  3548     __INST(lastErrorNumber) = nil;
  3428     __INST(lastErrorNumber) = nil;
  3549     if ((__INST(handleType) == nil)
  3429     if ((__INST(handleType) == nil)
  3550      || (__INST(handleType) == @symbol(filePointer))
  3430      || (__INST(handleType) == @symbol(filePointer))
  3551      || (__INST(handleType) == @symbol(socketFilePointer))
  3431      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3432      || (__INST(handleType) == @symbol(socketHandle))
  3552      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3433      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3553 	if (((fp = __INST(handle)) != nil)
  3434         if (((fp = __INST(handle)) != nil)
  3554 	    && (__INST(mode) != @symbol(writeonly))
  3435             && (__INST(mode) != @symbol(writeonly))
  3555 	    && __bothSmallInteger(count, start)
  3436             && __bothSmallInteger(count, start)
  3556 	) {
  3437         ) {
  3557 	    f = __FILEVal(fp);
  3438             f = __FILEVal(fp);
  3558 
  3439 
  3559 	    cnt = __intVal(count);
  3440             cnt = __intVal(count);
  3560 	    offs = __intVal(start) - 1;
  3441             offs = __intVal(start) - 1;
  3561 
  3442 
  3562 	    if (__isExternalBytesLike(anObject)) {
  3443             if (__isExternalBytesLike(anObject)) {
  3563 		OBJ sz;
  3444                 OBJ sz;
  3564 
  3445 
  3565 		nInstBytes = 0;
  3446                 nInstBytes = 0;
  3566 		extPtr = (char *)(__externalBytesAddress(anObject));
  3447                 extPtr = (char *)(__externalBytesAddress(anObject));
  3567 		if (extPtr == NULL) goto bad;
  3448                 if (extPtr == NULL) goto bad;
  3568 		sz = __externalBytesSize(anObject);
  3449                 sz = __externalBytesSize(anObject);
  3569 		if (__isSmallInteger(sz)) {
  3450                 if (__isSmallInteger(sz)) {
  3570 		    objSize = __intVal(sz);
  3451                     objSize = __intVal(sz);
  3571 		} else {
  3452                 } else {
  3572 		    objSize = 0; /* unknown */
  3453                     objSize = 0; /* unknown */
  3573 		}
  3454                 }
  3574 	    } else {
  3455             } else {
  3575 		OBJ oClass = __Class(anObject);
  3456                 OBJ oClass = __Class(anObject);
  3576 		int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3457                 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  3577 
  3458 
  3578 		nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3459                 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  3579 		switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3460                 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  3580 		    case BYTEARRAY:
  3461                     case BYTEARRAY:
  3581 		    case WORDARRAY:
  3462                     case WORDARRAY:
  3582 		    case LONGARRAY:
  3463                     case LONGARRAY:
  3583 		    case SWORDARRAY:
  3464                     case SWORDARRAY:
  3584 		    case SLONGARRAY:
  3465                     case SLONGARRAY:
  3585 		    case FLOATARRAY:
  3466                     case FLOATARRAY:
  3586 			break;
  3467                         break;
  3587 		    case DOUBLEARRAY:
  3468                     case DOUBLEARRAY:
  3588 #ifdef __NEED_DOUBLE_ALIGN
  3469 #ifdef __NEED_DOUBLE_ALIGN
  3589 			nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3470                         nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  3590 #endif
  3471 #endif
  3591 			break;
  3472                         break;
  3592 		    case LONGLONGARRAY:
  3473                     case LONGLONGARRAY:
  3593 		    case SLONGLONGARRAY:
  3474                     case SLONGLONGARRAY:
  3594 #ifdef __NEED_LONGLONG_ALIGN
  3475 #ifdef __NEED_LONGLONG_ALIGN
  3595 			nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3476                         nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  3596 #endif
  3477 #endif
  3597 			break;
  3478                         break;
  3598 		    default:
  3479                     default:
  3599 			goto bad;
  3480                         goto bad;
  3600 		}
  3481                 }
  3601 		extPtr = (char *)0;
  3482                 extPtr = (char *)0;
  3602 		objSize = __Size(anObject) - nInstBytes;
  3483                 objSize = __Size(anObject) - nInstBytes;
  3603 	    }
  3484             }
  3604 	    if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3485             if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) {
  3605 		_buffered = (__INST(buffered) == true);
  3486                 _buffered = (__INST(buffered) == true);
  3606 		if (_buffered) {
  3487                 if (_buffered) {
  3607 		    __READING__(f);
  3488                     __READING__(f);
  3608 		}
  3489                 }
  3609 
  3490 
  3610 		if (extPtr) {
  3491                 if (extPtr) {
  3611 		    __READBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3492                     __READBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType));
  3612 		} else {
  3493                 } else {
  3613 		    /*
  3494                     /*
  3614 		     * on interrupt, anObject may be moved to another location.
  3495                      * on interrupt, anObject may be moved to another location.
  3615 		     * So we pass anObject, and the offset to the __READBYTES_OBJ__ macro.
  3496                      * So we pass anObject, and the offset to the __READBYTES_OBJ__ macro.
  3616 		     */
  3497                      */
  3617 		    offs += nInstBytes;
  3498                     offs += nInstBytes;
  3618 		    __READBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3499                     __READBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType));
  3619 		}
  3500                 }
  3620 
  3501 
  3621 		if (ret > 0) {
  3502                 if (ret > 0) {
  3622 		    if (__isSmallInteger(__INST(position))) {
  3503                     if (__isSmallInteger(__INST(position))) {
  3623 			INT np = __intVal(__INST(position)) + ret;
  3504                         INT np = __intVal(__INST(position)) + ret;
  3624 			OBJ t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3505                         OBJ t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3625 		    } else {
  3506                     } else {
  3626 			__INST(position) = nil; /* i.e. do not know */
  3507                         __INST(position) = nil; /* i.e. do not know */
  3627 		    }
  3508                     }
  3628 		    RETURN (__mkSmallInteger(ret));
  3509                     RETURN (__mkSmallInteger(ret));
  3629 		}
  3510                 }
  3630 		if (ret == 0) {
  3511                 if (ret == 0) {
  3631 		    __INST(hitEOF) = true;
  3512                     __INST(hitEOF) = true;
  3632 		} else /* ret < 0 */ {
  3513                 } else /* ret < 0 */ {
  3633 		    __INST(position) = nil;
  3514                     __INST(position) = nil;
  3634 		    error = __mkSmallInteger(__threadErrno);
  3515                     error = __mkSmallInteger(__threadErrno);
  3635 		}
  3516                 }
  3636 	    }
  3517             }
  3637 	}
  3518         }
  3638     }
  3519     }
  3639 bad: ;
  3520 bad: ;
  3640 %}.
  3521 %}.
  3641     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3522     (hitEOF and:[self pastEndRead isNil]) ifTrue:[^ 0].
  3642     error notNil ifTrue:[
  3523     error notNil ifTrue:[
  3643 	lastErrorNumber := error.
  3524         lastErrorNumber := error.
  3644 	^ self readError:error
  3525         ^ self readError:error
  3645     ].
  3526     ].
  3646     handle isNil ifTrue:[^ self errorNotOpen].
  3527     handle isNil ifTrue:[^ self errorNotOpen].
  3647     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3528     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3648     "
  3529     "
  3649      count not integer or arg not bit-like (String, ByteArray etc)
  3530      count not integer or arg not bit-like (String, ByteArray etc)
  3673 
  3554 
  3674     __INST(lastErrorNumber) = nil;
  3555     __INST(lastErrorNumber) = nil;
  3675     if ((__INST(handleType) == nil)
  3556     if ((__INST(handleType) == nil)
  3676      || (__INST(handleType) == @symbol(filePointer))
  3557      || (__INST(handleType) == @symbol(filePointer))
  3677      || (__INST(handleType) == @symbol(socketFilePointer))
  3558      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3559      || (__INST(handleType) == @symbol(socketHandle))
  3678      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3560      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3679 	if (((fp = __INST(handle)) != nil)
  3561         if (((fp = __INST(handle)) != nil)
  3680 	    && (__INST(mode) != @symbol(writeonly))
  3562             && (__INST(mode) != @symbol(writeonly))
  3681 	) {
  3563         ) {
  3682 	    FILEPOINTER f;
  3564             FILEPOINTER f;
  3683 	    int ret, _buffered;
  3565             int ret, _buffered;
  3684 	    int value;
  3566             int value;
  3685 	    union {
  3567             union {
  3686 		unsigned char buffer[4];
  3568                 unsigned char buffer[4];
  3687 		int intVal;
  3569                 int intVal;
  3688 	    } u;
  3570             } u;
  3689 
  3571 
  3690 	    f = __FILEVal(fp);
  3572             f = __FILEVal(fp);
  3691 	    _buffered = (__INST(buffered) == true);
  3573             _buffered = (__INST(buffered) == true);
  3692 	    if (_buffered) {
  3574             if (_buffered) {
  3693 		__READING__(f)
  3575                 __READING__(f)
  3694 	    }
  3576             }
  3695 	    __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType));
  3577             __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType));
  3696 
  3578 
  3697 	    if (ret == 4) {
  3579             if (ret == 4) {
  3698 		if (__isSmallInteger(__INST(position))) {
  3580                 if (__isSmallInteger(__INST(position))) {
  3699 		    INT np = __intVal(__INST(position)) + 4;
  3581                     INT np = __intVal(__INST(position)) + 4;
  3700 		    OBJ t;
  3582                     OBJ t;
  3701 
  3583 
  3702 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3584                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3703 		} else {
  3585                 } else {
  3704 		    __INST(position) = nil; /* i.e. do not know */
  3586                     __INST(position) = nil; /* i.e. do not know */
  3705 		}
  3587                 }
  3706 		if (msbFlag == true) {
  3588                 if (msbFlag == true) {
  3707 #if defined(__MSBFIRST__)
  3589 #if defined(__MSBFIRST__)
  3708 		    value = u.intVal;
  3590                     value = u.intVal;
  3709 #else
  3591 #else
  3710 		    value = (u.buffer[0] & 0xFF);
  3592                     value = (u.buffer[0] & 0xFF);
  3711 		    value = (value << 8) | (u.buffer[1] & 0xFF);
  3593                     value = (value << 8) | (u.buffer[1] & 0xFF);
  3712 		    value = (value << 8) | (u.buffer[2] & 0xFF);
  3594                     value = (value << 8) | (u.buffer[2] & 0xFF);
  3713 		    value = (value << 8) | (u.buffer[3] & 0xFF);
  3595                     value = (value << 8) | (u.buffer[3] & 0xFF);
  3714 #endif
  3596 #endif
  3715 		} else {
  3597                 } else {
  3716 #if defined(__LSBFIRST__)
  3598 #if defined(__LSBFIRST__)
  3717 		    value = u.intVal;
  3599                     value = u.intVal;
  3718 #else
  3600 #else
  3719 		    value = (u.buffer[3] & 0xFF);
  3601                     value = (u.buffer[3] & 0xFF);
  3720 		    value = (value << 8) | (u.buffer[2] & 0xFF);
  3602                     value = (value << 8) | (u.buffer[2] & 0xFF);
  3721 		    value = (value << 8) | (u.buffer[1] & 0xFF);
  3603                     value = (value << 8) | (u.buffer[1] & 0xFF);
  3722 		    value = (value << 8) | (u.buffer[0] & 0xFF);
  3604                     value = (value << 8) | (u.buffer[0] & 0xFF);
  3723 #endif
  3605 #endif
  3724 		}
  3606                 }
  3725 #if __POINTER_SIZE__ == 8
  3607 #if __POINTER_SIZE__ == 8
  3726 		RETURN ( __mkSmallInteger(value));
  3608                 RETURN ( __mkSmallInteger(value));
  3727 #else
  3609 #else
  3728 		if ((value >= _MIN_INT) && (value <= _MAX_INT)) {
  3610                 if ((value >= _MIN_INT) && (value <= _MAX_INT)) {
  3729 		    RETURN ( __mkSmallInteger(value));
  3611                     RETURN ( __mkSmallInteger(value));
  3730 		}
  3612                 }
  3731 		RETURN ( __MKLARGEINT(value) );
  3613                 RETURN ( __MKLARGEINT(value) );
  3732 #endif
  3614 #endif
  3733 	    }
  3615             }
  3734 
  3616 
  3735 	    if (ret < 0) {
  3617             if (ret < 0) {
  3736 		__INST(position) = nil;
  3618                 __INST(position) = nil;
  3737 		error = __mkSmallInteger(__threadErrno);
  3619                 error = __mkSmallInteger(__threadErrno);
  3738 	    } else /* ret == 0 */ {
  3620             } else /* ret == 0 */ {
  3739 		__INST(hitEOF) = true;
  3621                 __INST(hitEOF) = true;
  3740 	    }
  3622             }
  3741 	}
  3623         }
  3742     }
  3624     }
  3743 %}.
  3625 %}.
  3744     hitEOF ifTrue:[^ self pastEndRead].
  3626     hitEOF ifTrue:[^ self pastEndRead].
  3745     handle isNil ifTrue:[^ self errorNotOpen].
  3627     handle isNil ifTrue:[^ self errorNotOpen].
  3746     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3628     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3761 
  3643 
  3762     __INST(lastErrorNumber) = nil;
  3644     __INST(lastErrorNumber) = nil;
  3763     if ((__INST(handleType) == nil)
  3645     if ((__INST(handleType) == nil)
  3764      || (__INST(handleType) == @symbol(filePointer))
  3646      || (__INST(handleType) == @symbol(filePointer))
  3765      || (__INST(handleType) == @symbol(socketFilePointer))
  3647      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3648      || (__INST(handleType) == @symbol(socketHandle))
  3766      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3649      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3767 	if (((fp = __INST(handle)) != nil)
  3650         if (((fp = __INST(handle)) != nil)
  3768 	    && (__INST(mode) != @symbol(writeonly))
  3651             && (__INST(mode) != @symbol(writeonly))
  3769 	) {
  3652         ) {
  3770 	    FILEPOINTER f;
  3653             FILEPOINTER f;
  3771 	    int ret, _buffered;
  3654             int ret, _buffered;
  3772 	    short value;
  3655             short value;
  3773 	    union {
  3656             union {
  3774 		unsigned char buffer[2];
  3657                 unsigned char buffer[2];
  3775 		short shortVal;
  3658                 short shortVal;
  3776 	    } u;
  3659             } u;
  3777 
  3660 
  3778 	    f = __FILEVal(fp);
  3661             f = __FILEVal(fp);
  3779 	    _buffered = (__INST(buffered) == true);
  3662             _buffered = (__INST(buffered) == true);
  3780 	    if (_buffered) {
  3663             if (_buffered) {
  3781 		__READING__(f)
  3664                 __READING__(f)
  3782 	    }
  3665             }
  3783 	    __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType));
  3666             __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType));
  3784 
  3667 
  3785 	    if (ret == 2) {
  3668             if (ret == 2) {
  3786 		if (__isSmallInteger(__INST(position))) {
  3669                 if (__isSmallInteger(__INST(position))) {
  3787 		    INT np = __intVal(__INST(position)) + 2;
  3670                     INT np = __intVal(__INST(position)) + 2;
  3788 		    OBJ t;
  3671                     OBJ t;
  3789 
  3672 
  3790 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3673                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3791 		} else {
  3674                 } else {
  3792 		    __INST(position) = nil; /* i.e. do not know */
  3675                     __INST(position) = nil; /* i.e. do not know */
  3793 		}
  3676                 }
  3794 		if (msbFlag == true) {
  3677                 if (msbFlag == true) {
  3795 #if defined(__MSBFIRST__)
  3678 #if defined(__MSBFIRST__)
  3796 		    value = u.shortVal;
  3679                     value = u.shortVal;
  3797 #else
  3680 #else
  3798 		    value = ((u.buffer[0] & 0xFF) << 8) | (u.buffer[1] & 0xFF);
  3681                     value = ((u.buffer[0] & 0xFF) << 8) | (u.buffer[1] & 0xFF);
  3799 #endif
  3682 #endif
  3800 		} else {
  3683                 } else {
  3801 #if defined(__LSBFIRST__)
  3684 #if defined(__LSBFIRST__)
  3802 		    value = u.shortVal;
  3685                     value = u.shortVal;
  3803 #else
  3686 #else
  3804 		    value = ((u.buffer[1] & 0xFF) << 8) | (u.buffer[0] & 0xFF);
  3687                     value = ((u.buffer[1] & 0xFF) << 8) | (u.buffer[0] & 0xFF);
  3805 #endif
  3688 #endif
  3806 		}
  3689                 }
  3807 		RETURN (__mkSmallInteger(value));
  3690                 RETURN (__mkSmallInteger(value));
  3808 	    }
  3691             }
  3809 
  3692 
  3810 	    if (ret < 0) {
  3693             if (ret < 0) {
  3811 		__INST(position) = nil; /* i.e. do not know */
  3694                 __INST(position) = nil; /* i.e. do not know */
  3812 		error = __mkSmallInteger(__threadErrno);
  3695                 error = __mkSmallInteger(__threadErrno);
  3813 	    } else /* ret == 0 */ {
  3696             } else /* ret == 0 */ {
  3814 		__INST(hitEOF) = true;
  3697                 __INST(hitEOF) = true;
  3815 	    }
  3698             }
  3816 	}
  3699         }
  3817     }
  3700     }
  3818 %}.
  3701 %}.
  3819     hitEOF ifTrue:[^ self pastEndRead].
  3702     hitEOF ifTrue:[^ self pastEndRead].
  3820     handle isNil ifTrue:[^ self errorNotOpen].
  3703     handle isNil ifTrue:[^ self errorNotOpen].
  3821     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3704     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3837 
  3720 
  3838     __INST(lastErrorNumber) = nil;
  3721     __INST(lastErrorNumber) = nil;
  3839     if ((__INST(handleType) == nil)
  3722     if ((__INST(handleType) == nil)
  3840      || (__INST(handleType) == @symbol(filePointer))
  3723      || (__INST(handleType) == @symbol(filePointer))
  3841      || (__INST(handleType) == @symbol(socketFilePointer))
  3724      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3725      || (__INST(handleType) == @symbol(socketHandle))
  3842      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3726      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3843 	if (((fp = __INST(handle)) != nil)
  3727         if (((fp = __INST(handle)) != nil)
  3844 	    && (__INST(mode) != @symbol(writeonly))
  3728             && (__INST(mode) != @symbol(writeonly))
  3845 	) {
  3729         ) {
  3846 	    FILEPOINTER f;
  3730             FILEPOINTER f;
  3847 	    int ret, _buffered;
  3731             int ret, _buffered;
  3848 	    unsigned INT value;
  3732             unsigned INT value;
  3849 	    union {
  3733             union {
  3850 		unsigned char buffer[4];
  3734                 unsigned char buffer[4];
  3851 		unsigned int intVal;
  3735                 unsigned int intVal;
  3852 	    } u;
  3736             } u;
  3853 
  3737 
  3854 	    f = __FILEVal(fp);
  3738             f = __FILEVal(fp);
  3855 	    _buffered = (__INST(buffered) == true);
  3739             _buffered = (__INST(buffered) == true);
  3856 	    if (_buffered) {
  3740             if (_buffered) {
  3857 		__READING__(f)
  3741                 __READING__(f)
  3858 	    }
  3742             }
  3859 	    __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType));
  3743             __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType));
  3860 
  3744 
  3861 	    if (ret == 4) {
  3745             if (ret == 4) {
  3862 		if (__isSmallInteger(__INST(position))) {
  3746                 if (__isSmallInteger(__INST(position))) {
  3863 		    INT np = __intVal(__INST(position)) + 4;
  3747                     INT np = __intVal(__INST(position)) + 4;
  3864 		    OBJ t;
  3748                     OBJ t;
  3865 
  3749 
  3866 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3750                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3867 		} else {
  3751                 } else {
  3868 		    __INST(position) = nil; /* i.e. do not know */
  3752                     __INST(position) = nil; /* i.e. do not know */
  3869 		}
  3753                 }
  3870 		if (msbFlag == true) {
  3754                 if (msbFlag == true) {
  3871 #if defined(__MSBFIRST__)
  3755 #if defined(__MSBFIRST__)
  3872 		    value = u.intVal;
  3756                     value = u.intVal;
  3873 #else
  3757 #else
  3874 		    value = u.buffer[0];
  3758                     value = u.buffer[0];
  3875 		    value = (value << 8) | u.buffer[1];
  3759                     value = (value << 8) | u.buffer[1];
  3876 		    value = (value << 8) | u.buffer[2];
  3760                     value = (value << 8) | u.buffer[2];
  3877 		    value = (value << 8) | u.buffer[3];
  3761                     value = (value << 8) | u.buffer[3];
  3878 #endif
  3762 #endif
  3879 		} else {
  3763                 } else {
  3880 #if defined(__LSBFIRST__)
  3764 #if defined(__LSBFIRST__)
  3881 		    value = u.intVal;
  3765                     value = u.intVal;
  3882 #else
  3766 #else
  3883 		    value = u.buffer[3];
  3767                     value = u.buffer[3];
  3884 		    value = (value << 8) | u.buffer[2];
  3768                     value = (value << 8) | u.buffer[2];
  3885 		    value = (value << 8) | u.buffer[1];
  3769                     value = (value << 8) | u.buffer[1];
  3886 		    value = (value << 8) | u.buffer[0];
  3770                     value = (value << 8) | u.buffer[0];
  3887 #endif
  3771 #endif
  3888 		}
  3772                 }
  3889 #if __POINTER_SIZE__ == 8
  3773 #if __POINTER_SIZE__ == 8
  3890 		value &= 0xFFFFFFFF;
  3774                 value &= 0xFFFFFFFF;
  3891 		RETURN (__mkSmallInteger(value));
  3775                 RETURN (__mkSmallInteger(value));
  3892 #else
  3776 #else
  3893 		if (value <= _MAX_INT) {
  3777                 if (value <= _MAX_INT) {
  3894 		    RETURN (__mkSmallInteger(value));
  3778                     RETURN (__mkSmallInteger(value));
  3895 		}
  3779                 }
  3896 		RETURN (__MKULARGEINT(value) );
  3780                 RETURN (__MKULARGEINT(value) );
  3897 #endif
  3781 #endif
  3898 	    }
  3782             }
  3899 
  3783 
  3900 	    if (ret < 0) {
  3784             if (ret < 0) {
  3901 		__INST(position) = nil; /* i.e. do not know */
  3785                 __INST(position) = nil; /* i.e. do not know */
  3902 		error = __mkSmallInteger(__threadErrno);
  3786                 error = __mkSmallInteger(__threadErrno);
  3903 	    } else /* ret == 0 */ {
  3787             } else /* ret == 0 */ {
  3904 		__INST(hitEOF) = true;
  3788                 __INST(hitEOF) = true;
  3905 	    }
  3789             }
  3906 	}
  3790         }
  3907     }
  3791     }
  3908 %}.
  3792 %}.
  3909     hitEOF ifTrue:[^ self pastEndRead].
  3793     hitEOF ifTrue:[^ self pastEndRead].
  3910     handle isNil ifTrue:[^ self errorNotOpen].
  3794     handle isNil ifTrue:[^ self errorNotOpen].
  3911     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3795     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3926 
  3810 
  3927     __INST(lastErrorNumber) = nil;
  3811     __INST(lastErrorNumber) = nil;
  3928     if ((__INST(handleType) == nil)
  3812     if ((__INST(handleType) == nil)
  3929      || (__INST(handleType) == @symbol(filePointer))
  3813      || (__INST(handleType) == @symbol(filePointer))
  3930      || (__INST(handleType) == @symbol(socketFilePointer))
  3814      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3815      || (__INST(handleType) == @symbol(socketHandle))
  3931      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3816      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3932 	if (((fp = __INST(handle)) != nil)
  3817         if (((fp = __INST(handle)) != nil)
  3933 	    && (__INST(mode) != @symbol(writeonly))
  3818             && (__INST(mode) != @symbol(writeonly))
  3934 	) {
  3819         ) {
  3935 	    FILEPOINTER f;
  3820             FILEPOINTER f;
  3936 	    int ret, _buffered;
  3821             int ret, _buffered;
  3937 	    unsigned int value;
  3822             unsigned int value;
  3938 	    union {
  3823             union {
  3939 		unsigned char buffer[2];
  3824                 unsigned char buffer[2];
  3940 		unsigned short shortVal;
  3825                 unsigned short shortVal;
  3941 	    } u;
  3826             } u;
  3942 
  3827 
  3943 	    f = __FILEVal(fp);
  3828             f = __FILEVal(fp);
  3944 	    _buffered = (__INST(buffered) == true);
  3829             _buffered = (__INST(buffered) == true);
  3945 	    if (_buffered) {
  3830             if (_buffered) {
  3946 		__READING__(f)
  3831                 __READING__(f)
  3947 	    }
  3832             }
  3948 	    __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType));
  3833             __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType));
  3949 
  3834 
  3950 	    if (ret == 2) {
  3835             if (ret == 2) {
  3951 		if (__isSmallInteger(__INST(position))) {
  3836                 if (__isSmallInteger(__INST(position))) {
  3952 		    INT np = __intVal(__INST(position)) + 2;
  3837                     INT np = __intVal(__INST(position)) + 2;
  3953 		    OBJ t;
  3838                     OBJ t;
  3954 
  3839 
  3955 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3840                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3956 		} else {
  3841                 } else {
  3957 		    __INST(position) = nil; /* i.e. do not know */
  3842                     __INST(position) = nil; /* i.e. do not know */
  3958 		}
  3843                 }
  3959 		if (msbFlag == true) {
  3844                 if (msbFlag == true) {
  3960 #if defined(__MSBFIRST__)
  3845 #if defined(__MSBFIRST__)
  3961 		    value = u.shortVal;
  3846                     value = u.shortVal;
  3962 #else
  3847 #else
  3963 		    value = (u.buffer[0] << 8) | u.buffer[1];
  3848                     value = (u.buffer[0] << 8) | u.buffer[1];
  3964 #endif
  3849 #endif
  3965 		} else {
  3850                 } else {
  3966 #if defined(__LSBFIRST__)
  3851 #if defined(__LSBFIRST__)
  3967 		    value = u.shortVal;
  3852                     value = u.shortVal;
  3968 #else
  3853 #else
  3969 		    value = (u.buffer[1] << 8) | u.buffer[0];
  3854                     value = (u.buffer[1] << 8) | u.buffer[0];
  3970 #endif
  3855 #endif
  3971 		}
  3856                 }
  3972 		RETURN (__mkSmallInteger(value));
  3857                 RETURN (__mkSmallInteger(value));
  3973 	    }
  3858             }
  3974 
  3859 
  3975 	    if (ret < 0) {
  3860             if (ret < 0) {
  3976 		__INST(position) = nil; /* i.e. do not know */
  3861                 __INST(position) = nil; /* i.e. do not know */
  3977 		error = __mkSmallInteger(__threadErrno);
  3862                 error = __mkSmallInteger(__threadErrno);
  3978 	    } else /* ret == 0 */ {
  3863             } else /* ret == 0 */ {
  3979 		__INST(hitEOF) = true;
  3864                 __INST(hitEOF) = true;
  3980 	    }
  3865             }
  3981 	}
  3866         }
  3982     }
  3867     }
  3983 %}.
  3868 %}.
  3984     hitEOF ifTrue:[^ self pastEndRead].
  3869     hitEOF ifTrue:[^ self pastEndRead].
  3985     handle isNil ifTrue:[^ self errorNotOpen].
  3870     handle isNil ifTrue:[^ self errorNotOpen].
  3986     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  3871     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4008 
  3893 
  4009 nextPutByte:aByteValue
  3894 nextPutByte:aByteValue
  4010     "write a byte.
  3895     "write a byte.
  4011      Works in both binary and text modes."
  3896      Works in both binary and text modes."
  4012 
  3897 
  4013 |error|
  3898     |error|
  4014 
  3899 
  4015 %{
  3900 %{
  4016     FILEPOINTER f;
  3901     FILEPOINTER f;
  4017     char c;
  3902     char c;
  4018     OBJ fp;
  3903     OBJ fp;
  4020 
  3905 
  4021     __INST(lastErrorNumber) = nil;
  3906     __INST(lastErrorNumber) = nil;
  4022     if ((__INST(handleType) == nil)
  3907     if ((__INST(handleType) == nil)
  4023      || (__INST(handleType) == @symbol(filePointer))
  3908      || (__INST(handleType) == @symbol(filePointer))
  4024      || (__INST(handleType) == @symbol(socketFilePointer))
  3909      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3910      || (__INST(handleType) == @symbol(socketHandle))
  4025      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3911      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4026 	if (((fp = __INST(handle)) != nil)
  3912         if (((fp = __INST(handle)) != nil)
  4027 	    && (__INST(mode) != @symbol(readonly))
  3913             && (__INST(mode) != @symbol(readonly))
  4028 	    && __isSmallInteger(aByteValue)
  3914             && __isSmallInteger(aByteValue)
  4029 
  3915 
  4030 	) {
  3916         ) {
  4031 	    c = __intVal(aByteValue);
  3917             c = __intVal(aByteValue);
  4032 	    f = __FILEVal(fp);
  3918             f = __FILEVal(fp);
  4033 	    if (_buffered = (__INST(buffered) == true)) {
  3919             if (_buffered = (__INST(buffered) == true)) {
  4034 		__WRITING__(f)
  3920                 __WRITING__(f)
  4035 	    }
  3921             }
  4036 #ifdef WIN32
  3922 #ifdef WIN32
  4037 	    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  3923             if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  4038 		cnt = __win32_fwrite(&c, 1, 1, f);
  3924                 cnt = __win32_fwrite(&c, 1, 1, f);
  4039 	    } else
  3925             } else
  4040 #endif
  3926 #endif
  4041 	    {
  3927             {
  4042 		__WRITEBYTE__(cnt, f, &c, _buffered, __INST(handleType));
  3928                 __WRITEBYTE__(cnt, f, &c, _buffered, __INST(handleType));
  4043 	    }
  3929             }
  4044 	    if (cnt == 1) {
  3930             if (cnt == 1) {
  4045 		if (__isSmallInteger(__INST(position))) {
  3931                 if (__isSmallInteger(__INST(position))) {
  4046 		    INT np = __intVal(__INST(position)) + 1;
  3932                     INT np = __intVal(__INST(position)) + 1;
  4047 		    OBJ t;
  3933                     OBJ t;
  4048 
  3934 
  4049 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  3935                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4050 		} else {
  3936                 } else {
  4051 		    __INST(position) = nil; /* i.e. do not know */
  3937                     __INST(position) = nil; /* i.e. do not know */
  4052 		}
  3938                 }
  4053 		RETURN (self);
  3939                 RETURN (self);
  4054 	    }
  3940             }
  4055 	    if (cnt < 0) {
  3941             if (cnt < 0) {
  4056 		__INST(position) = nil; /* i.e. do not know */
  3942                 __INST(position) = nil; /* i.e. do not know */
  4057 	    }
  3943             }
  4058 	    error = __mkSmallInteger(__threadErrno);
  3944             error = __mkSmallInteger(__threadErrno);
  4059 	}
  3945         }
  4060     }
  3946     }
  4061 %}.
  3947 %}.
  4062     handle isNil ifTrue:[self errorNotOpen. ^ self].
  3948     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4063     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  3949     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4064     lastErrorNumber := error.
  3950     lastErrorNumber := error.
  4072      (i.e. be a ByteArray, String, Float- or DoubleArray),
  3958      (i.e. be a ByteArray, String, Float- or DoubleArray),
  4073      or an externalBytes object (with known size).
  3959      or an externalBytes object (with known size).
  4074 
  3960 
  4075      Use with care - non object oriented i/o.
  3961      Use with care - non object oriented i/o.
  4076      Warning:
  3962      Warning:
  4077 	in general, you cannot use this method to pass non-byte data to other
  3963         in general, you cannot use this method to pass non-byte data to other
  4078 	architectures (unless you prepared the buffer with care),
  3964         architectures (unless you prepared the buffer with care),
  4079 	since it does not care for byte order or float representation."
  3965         since it does not care for byte order or float representation."
  4080 
  3966 
  4081     |error|
  3967     |error|
  4082 
  3968 
  4083 %{
  3969 %{
  4084     FILEPOINTER f;
  3970     FILEPOINTER f;
  4089 
  3975 
  4090     __INST(lastErrorNumber) = nil;
  3976     __INST(lastErrorNumber) = nil;
  4091     if ((__INST(handleType) == nil)
  3977     if ((__INST(handleType) == nil)
  4092      || (__INST(handleType) == @symbol(filePointer))
  3978      || (__INST(handleType) == @symbol(filePointer))
  4093      || (__INST(handleType) == @symbol(socketFilePointer))
  3979      || (__INST(handleType) == @symbol(socketFilePointer))
       
  3980      || (__INST(handleType) == @symbol(socketHandle))
  4094      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  3981      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4095 	if (((fp = __INST(handle)) != nil)
  3982         if (((fp = __INST(handle)) != nil)
  4096 	    && (__INST(mode) != @symbol(readonly))
  3983             && (__INST(mode) != @symbol(readonly))
  4097 	    && __bothSmallInteger(count, start)
  3984             && __bothSmallInteger(count, start)
  4098 	) {
  3985         ) {
  4099 	    len = __intVal(count);
  3986             len = __intVal(count);
  4100 	    offs = __intVal(start) - 1;
  3987             offs = __intVal(start) - 1;
  4101 	    f = __FILEVal(fp);
  3988             f = __FILEVal(fp);
  4102 
  3989 
  4103 	    if (__isExternalBytesLike(anObject)) {
  3990             if (__isExternalBytesLike(anObject)) {
  4104 		OBJ sz;
  3991                 OBJ sz;
  4105 
  3992 
  4106 		nInstBytes = 0;
  3993                 nInstBytes = 0;
  4107 		extPtr = (char *)__externalBytesAddress(anObject);
  3994                 extPtr = (char *)__externalBytesAddress(anObject);
  4108 		if (extPtr == NULL) goto bad;
  3995                 if (extPtr == NULL) goto bad;
  4109 		sz = __externalBytesSize(anObject);
  3996                 sz = __externalBytesSize(anObject);
  4110 		if (__isSmallInteger(sz)) {
  3997                 if (__isSmallInteger(sz)) {
  4111 		    objSize = __intVal(sz);
  3998                     objSize = __intVal(sz);
  4112 		} else {
  3999                 } else {
  4113 		    objSize = 0; /* unknown */
  4000                     objSize = 0; /* unknown */
  4114 		}
  4001                 }
  4115 	    } else {
  4002             } else {
  4116 		OBJ oClass = __Class(anObject);
  4003                 OBJ oClass = __Class(anObject);
  4117 		int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  4004                 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
  4118 
  4005 
  4119 		nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  4006                 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
  4120 		switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  4007                 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
  4121 		    case BYTEARRAY:
  4008                     case BYTEARRAY:
  4122 		    case WORDARRAY:
  4009                     case WORDARRAY:
  4123 		    case LONGARRAY:
  4010                     case LONGARRAY:
  4124 		    case SWORDARRAY:
  4011                     case SWORDARRAY:
  4125 		    case SLONGARRAY:
  4012                     case SLONGARRAY:
  4126 		    case FLOATARRAY:
  4013                     case FLOATARRAY:
  4127 			break;
  4014                         break;
  4128 		    case DOUBLEARRAY:
  4015                     case DOUBLEARRAY:
  4129 #ifdef __NEED_DOUBLE_ALIGN
  4016 #ifdef __NEED_DOUBLE_ALIGN
  4130 			nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  4017                         nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1);
  4131 #endif
  4018 #endif
  4132 			break;
  4019                         break;
  4133 		    case LONGLONGARRAY:
  4020                     case LONGLONGARRAY:
  4134 		    case SLONGLONGARRAY:
  4021                     case SLONGLONGARRAY:
  4135 #ifdef __NEED_LONGLONG_ALIGN
  4022 #ifdef __NEED_LONGLONG_ALIGN
  4136 			nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  4023                         nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1);
  4137 #endif
  4024 #endif
  4138 			break;
  4025                         break;
  4139 		    default:
  4026                     default:
  4140 			goto bad;
  4027                         goto bad;
  4141 		}
  4028                 }
  4142 		extPtr = (char *)0;
  4029                 extPtr = (char *)0;
  4143 		objSize = __Size(anObject) - nInstBytes;
  4030                 objSize = __Size(anObject) - nInstBytes;
  4144 	    }
  4031             }
  4145 	    if ( (offs >= 0) && (len >= 0) && (objSize >= (len + offs)) ) {
  4032             if ( (offs >= 0) && (len >= 0) && (objSize >= (len + offs)) ) {
  4146 		if (_buffered = (__INST(buffered) == true)) {
  4033                 if (_buffered = (__INST(buffered) == true)) {
  4147 		    __WRITING__(f)
  4034                     __WRITING__(f)
  4148 		}
  4035                 }
  4149 
  4036 
  4150 		if (extPtr) {
  4037                 if (extPtr) {
  4151 		    __WRITEBYTES__(cnt, f, extPtr+offs, len, _buffered, __INST(handleType));
  4038                     __WRITEBYTES__(cnt, f, extPtr+offs, len, _buffered, __INST(handleType));
  4152 		} else {
  4039                 } else {
  4153 		    /*
  4040                     /*
  4154 		     * on interrupt, anObject may be moved to another location.
  4041                      * on interrupt, anObject may be moved to another location.
  4155 		     * So we pass anObject, and the offset to the __WRITEBYTES_OBJ__ macro.
  4042                      * So we pass anObject, and the offset to the __WRITEBYTES_OBJ__ macro.
  4156 		     */
  4043                      */
  4157 		    offs += nInstBytes;
  4044                     offs += nInstBytes;
  4158 		    __WRITEBYTES_OBJ__(cnt, f, anObject, offs, len, _buffered, __INST(handleType));
  4045                     __WRITEBYTES_OBJ__(cnt, f, anObject, offs, len, _buffered, __INST(handleType));
  4159 		}
  4046                 }
  4160 
  4047 
  4161 		if (cnt >= 0) {
  4048                 if (cnt >= 0) {
  4162 		    if (__isSmallInteger(__INST(position))) {
  4049                     if (__isSmallInteger(__INST(position))) {
  4163 			INT np = __intVal(__INST(position)) + cnt;
  4050                         INT np = __intVal(__INST(position)) + cnt;
  4164 			OBJ t;
  4051                         OBJ t;
  4165 
  4052 
  4166 			t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4053                         t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4167 		    } else {
  4054                     } else {
  4168 			__INST(position) = nil; /* i.e. do not know */
  4055                         __INST(position) = nil; /* i.e. do not know */
  4169 		    }
  4056                     }
  4170 		    RETURN ( __mkSmallInteger(cnt) );
  4057                     RETURN ( __mkSmallInteger(cnt) );
  4171 		} else /* cnt < 0 */ {
  4058                 } else /* cnt < 0 */ {
  4172 		    if (
  4059                     if (
  4173 #ifdef EWOULDBLOCK
  4060 #ifdef EWOULDBLOCK
  4174 			(__threadErrno == EWOULDBLOCK) ||
  4061                         (__threadErrno == EWOULDBLOCK) ||
  4175 #endif
  4062 #endif
  4176 			(__threadErrno == EAGAIN)
  4063                         (__threadErrno == EAGAIN)
  4177 		    ) {
  4064                     ) {
  4178 			RETURN ( __mkSmallInteger(0) );
  4065                         RETURN ( __mkSmallInteger(0) );
  4179 		    }
  4066                     }
  4180 		    __INST(position) = nil; /* i.e. do not know */
  4067                     __INST(position) = nil; /* i.e. do not know */
  4181 		    error = __mkSmallInteger(__threadErrno);
  4068                     error = __mkSmallInteger(__threadErrno);
  4182 		}
  4069                 }
  4183 	    }
  4070             }
  4184 	}
  4071         }
  4185     }
  4072     }
  4186 bad: ;
  4073 bad: ;
  4187 %}.
  4074 %}.
  4188     error notNil ifTrue:[
  4075     error notNil ifTrue:[
  4189 	lastErrorNumber := error.
  4076         lastErrorNumber := error.
  4190 	self writeError:error.
  4077         self writeError:error.
  4191 	^ self
  4078         ^ self
  4192     ].
  4079     ].
  4193     handle isNil ifTrue:[^ self errorNotOpen].
  4080     handle isNil ifTrue:[^ self errorNotOpen].
  4194     (mode == #readonly) ifTrue:[^ self errorReadOnly].
  4081     (mode == #readonly) ifTrue:[^ self errorReadOnly].
  4195     ^ self primitiveFailed
  4082     ^ self primitiveFailed
  4196 !
  4083 !
  4204     |error|
  4091     |error|
  4205 
  4092 
  4206 %{
  4093 %{
  4207     int num;
  4094     int num;
  4208     union {
  4095     union {
  4209 	char bytes[4];
  4096         char bytes[4];
  4210 	int intVal;
  4097         int intVal;
  4211     } u;
  4098     } u;
  4212     FILEPOINTER f;
  4099     FILEPOINTER f;
  4213     int cnt, _buffered;
  4100     int cnt, _buffered;
  4214     OBJ fp;
  4101     OBJ fp;
  4215 
  4102 
  4216     __INST(lastErrorNumber) = nil;
  4103     __INST(lastErrorNumber) = nil;
  4217     if (__isSmallInteger(aNumber)) {
  4104     if (__isSmallInteger(aNumber)) {
  4218 	num = __intVal(aNumber);
  4105         num = __intVal(aNumber);
  4219     } else {
  4106     } else {
  4220 #if __POINTER_SIZE__ == 8
  4107 #if __POINTER_SIZE__ == 8
  4221 	goto badArg;
  4108         goto badArg;
  4222 #else
  4109 #else
  4223 	num = __longIntVal(aNumber);
  4110         num = __longIntVal(aNumber);
  4224 	if (num == 0) {
  4111         if (num == 0) {
  4225 	    num = __signedLongIntVal(aNumber);
  4112             num = __signedLongIntVal(aNumber);
  4226 	    if (num == 0) {
  4113             if (num == 0) {
  4227 		/* bad arg or out-of-range integer
  4114                 /* bad arg or out-of-range integer
  4228 		 * (handled by the fallBack code)
  4115                  * (handled by the fallBack code)
  4229 		 */
  4116                  */
  4230 		goto badArg;
  4117                 goto badArg;
  4231 	    }
  4118             }
  4232 	}
  4119         }
  4233 #endif
  4120 #endif
  4234     }
  4121     }
  4235 
  4122 
  4236     if ((__INST(handleType) == nil)
  4123     if ((__INST(handleType) == nil)
  4237      || (__INST(handleType) == @symbol(filePointer))
  4124      || (__INST(handleType) == @symbol(filePointer))
  4238      || (__INST(handleType) == @symbol(socketFilePointer))
  4125      || (__INST(handleType) == @symbol(socketFilePointer))
       
  4126      || (__INST(handleType) == @symbol(socketHandle))
  4239      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4127      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4240 	if (((fp = __INST(handle)) != nil)
  4128         if (((fp = __INST(handle)) != nil)
  4241 	 && (__INST(mode) != @symbol(readonly))
  4129          && (__INST(mode) != @symbol(readonly))
  4242 	) {
  4130         ) {
  4243 	    if (msbFlag == true) {
  4131             if (msbFlag == true) {
  4244 #if defined(__MSBFIRST__)
  4132 #if defined(__MSBFIRST__)
  4245 		u.intVal = num;
  4133                 u.intVal = num;
  4246 #else
  4134 #else
  4247 		u.bytes[0] = (num >> 24) & 0xFF;
  4135                 u.bytes[0] = (num >> 24) & 0xFF;
  4248 		u.bytes[1] = (num >> 16) & 0xFF;
  4136                 u.bytes[1] = (num >> 16) & 0xFF;
  4249 		u.bytes[2] = (num >> 8) & 0xFF;
  4137                 u.bytes[2] = (num >> 8) & 0xFF;
  4250 		u.bytes[3] = num & 0xFF;
  4138                 u.bytes[3] = num & 0xFF;
  4251 #endif
  4139 #endif
  4252 	    } else {
  4140             } else {
  4253 #if defined(__LSBFIRST__)
  4141 #if defined(__LSBFIRST__)
  4254 		u.intVal = num;
  4142                 u.intVal = num;
  4255 #else
  4143 #else
  4256 		u.bytes[3] = (num >> 24) & 0xFF;
  4144                 u.bytes[3] = (num >> 24) & 0xFF;
  4257 		u.bytes[2] = (num >> 16) & 0xFF;
  4145                 u.bytes[2] = (num >> 16) & 0xFF;
  4258 		u.bytes[1] = (num >> 8) & 0xFF;
  4146                 u.bytes[1] = (num >> 8) & 0xFF;
  4259 		u.bytes[0] = num & 0xFF;
  4147                 u.bytes[0] = num & 0xFF;
  4260 #endif
  4148 #endif
  4261 	    }
  4149             }
  4262 
  4150 
  4263 	    f = __FILEVal(fp);
  4151             f = __FILEVal(fp);
  4264 	    if (_buffered = (__INST(buffered) == true)) {
  4152             if (_buffered = (__INST(buffered) == true)) {
  4265 		__WRITING__(f)
  4153                 __WRITING__(f)
  4266 	    }
  4154             }
  4267 	    __WRITEBYTES__(cnt, f, u.bytes, 4, _buffered, __INST(handleType));
  4155             __WRITEBYTES__(cnt, f, u.bytes, 4, _buffered, __INST(handleType));
  4268 
  4156 
  4269 	    if (cnt == 4) {
  4157             if (cnt == 4) {
  4270 		if (__isSmallInteger(__INST(position))) {
  4158                 if (__isSmallInteger(__INST(position))) {
  4271 		    INT np = __intVal(__INST(position)) + 4;
  4159                     INT np = __intVal(__INST(position)) + 4;
  4272 		    OBJ t;
  4160                     OBJ t;
  4273 
  4161 
  4274 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4162                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4275 		} else {
  4163                 } else {
  4276 		    __INST(position) = nil; /* i.e. do not know */
  4164                     __INST(position) = nil; /* i.e. do not know */
  4277 		}
  4165                 }
  4278 		RETURN ( self );
  4166                 RETURN ( self );
  4279 	    }
  4167             }
  4280 	    __INST(position) = nil; /* i.e. do not know */
  4168             __INST(position) = nil; /* i.e. do not know */
  4281 	    error = __mkSmallInteger(__threadErrno);
  4169             error = __mkSmallInteger(__threadErrno);
  4282 	}
  4170         }
  4283     }
  4171     }
  4284 badArg: ;
  4172 badArg: ;
  4285 %}.
  4173 %}.
  4286     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4174     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4287     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4175     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4288     error notNil ifTrue:[
  4176     error notNil ifTrue:[
  4289 	lastErrorNumber := error.
  4177         lastErrorNumber := error.
  4290 	self writeError:error.
  4178         self writeError:error.
  4291 	^ self
  4179         ^ self
  4292     ].
  4180     ].
  4293 
  4181 
  4294     aNumber isInteger ifTrue:[
  4182     aNumber isInteger ifTrue:[
  4295 	^ super nextPutLong:aNumber MSB:msbFlag
  4183         ^ super nextPutLong:aNumber MSB:msbFlag
  4296     ].
  4184     ].
  4297     self argumentMustBeInteger
  4185     self argumentMustBeInteger
  4298 !
  4186 !
  4299 
  4187 
  4300 nextPutShort:anIntegerOrCharacter MSB:msbFlag
  4188 nextPutShort:anIntegerOrCharacter MSB:msbFlag
  4305 
  4193 
  4306     |error|
  4194     |error|
  4307 %{
  4195 %{
  4308     int num;
  4196     int num;
  4309     union {
  4197     union {
  4310 	char bytes[2];
  4198         char bytes[2];
  4311 	short shortVal;
  4199         short shortVal;
  4312     } u;
  4200     } u;
  4313 
  4201 
  4314     FILEPOINTER f;
  4202     FILEPOINTER f;
  4315     int cnt, _buffered;
  4203     int cnt, _buffered;
  4316     OBJ fp;
  4204     OBJ fp;
  4317 
  4205 
  4318     __INST(lastErrorNumber) = nil;
  4206     __INST(lastErrorNumber) = nil;
  4319     if ((__INST(handleType) == nil)
  4207     if ((__INST(handleType) == nil)
  4320      || (__INST(handleType) == @symbol(filePointer))
  4208      || (__INST(handleType) == @symbol(filePointer))
  4321      || (__INST(handleType) == @symbol(socketFilePointer))
  4209      || (__INST(handleType) == @symbol(socketFilePointer))
       
  4210      || (__INST(handleType) == @symbol(socketHandle))
  4322      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4211      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4323 	if (((fp = __INST(handle)) != nil)
  4212         if (((fp = __INST(handle)) != nil)
  4324 	    && (__INST(mode) != @symbol(readonly))
  4213             && (__INST(mode) != @symbol(readonly))
  4325 	) {
  4214         ) {
  4326 	    if (__isSmallInteger(anIntegerOrCharacter)) {
  4215             if (__isSmallInteger(anIntegerOrCharacter)) {
  4327 		num = __intVal(anIntegerOrCharacter);
  4216                 num = __intVal(anIntegerOrCharacter);
  4328 	    } else if (__isCharacter(anIntegerOrCharacter)) {
  4217             } else if (__isCharacter(anIntegerOrCharacter)) {
  4329 		num = __smallIntegerVal(__characterVal(anIntegerOrCharacter));
  4218                 num = __smallIntegerVal(__characterVal(anIntegerOrCharacter));
  4330 	    } else
  4219             } else
  4331 		goto out;
  4220                 goto out;
  4332 
  4221 
  4333 	    if (msbFlag == true) {
  4222             if (msbFlag == true) {
  4334 #if defined(__MSBFIRST__)
  4223 #if defined(__MSBFIRST__)
  4335 		u.shortVal = num;
  4224                 u.shortVal = num;
  4336 #else
  4225 #else
  4337 		u.bytes[0] = (num >> 8) & 0xFF;
  4226                 u.bytes[0] = (num >> 8) & 0xFF;
  4338 		u.bytes[1] = num & 0xFF;
  4227                 u.bytes[1] = num & 0xFF;
  4339 #endif
  4228 #endif
  4340 	    } else {
  4229             } else {
  4341 #if defined(__LSBFIRST__)
  4230 #if defined(__LSBFIRST__)
  4342 		u.shortVal = num;
  4231                 u.shortVal = num;
  4343 #else
  4232 #else
  4344 		u.bytes[1] = (num >> 8) & 0xFF;
  4233                 u.bytes[1] = (num >> 8) & 0xFF;
  4345 		u.bytes[0] = num & 0xFF;
  4234                 u.bytes[0] = num & 0xFF;
  4346 #endif
  4235 #endif
  4347 	    }
  4236             }
  4348 
  4237 
  4349 	    f = __FILEVal(fp);
  4238             f = __FILEVal(fp);
  4350 	    if (_buffered = (__INST(buffered) == true)) {
  4239             if (_buffered = (__INST(buffered) == true)) {
  4351 		__WRITING__(f)
  4240                 __WRITING__(f)
  4352 	    }
  4241             }
  4353 	    __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType));
  4242             __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType));
  4354 
  4243 
  4355 	    if (cnt == 2) {
  4244             if (cnt == 2) {
  4356 		if (__isSmallInteger(__INST(position))) {
  4245                 if (__isSmallInteger(__INST(position))) {
  4357 		    INT np = __intVal(__INST(position)) + 2;
  4246                     INT np = __intVal(__INST(position)) + 2;
  4358 		    OBJ t;
  4247                     OBJ t;
  4359 
  4248 
  4360 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4249                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  4361 		} else {
  4250                 } else {
  4362 		    __INST(position) = nil; /* i.e. do not know */
  4251                     __INST(position) = nil; /* i.e. do not know */
  4363 		}
  4252                 }
  4364 		RETURN ( self );
  4253                 RETURN ( self );
  4365 	    }
  4254             }
  4366 	    __INST(position) = nil; /* i.e. do not know */
  4255             __INST(position) = nil; /* i.e. do not know */
  4367 	    error = __mkSmallInteger(__threadErrno);
  4256             error = __mkSmallInteger(__threadErrno);
  4368 	}
  4257         }
  4369     }
  4258     }
  4370 out:;
  4259 out:;
  4371 %}.
  4260 %}.
  4372     error notNil ifTrue:[
  4261     error notNil ifTrue:[
  4373 	lastErrorNumber := error.
  4262         lastErrorNumber := error.
  4374 	self writeError:error.
  4263         self writeError:error.
  4375 	^ self
  4264         ^ self
  4376     ].
  4265     ].
  4377     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4266     handle isNil ifTrue:[self errorNotOpen. ^ self].
  4378     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4267     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  4379     self argumentMustBeInteger
  4268     self argumentMustBeInteger
  4380 ! !
  4269 ! !
  4411     "low level close - may be redefined in subclasses
  4300     "low level close - may be redefined in subclasses
  4412      Don't send this message, send #close instead"
  4301      Don't send this message, send #close instead"
  4413 
  4302 
  4414     |fp error|
  4303     |fp error|
  4415 
  4304 
       
  4305     fp := handle.
       
  4306 
  4416 %{
  4307 %{
  4417     if ((__INST(handleType) == nil) 
  4308     int rslt;
  4418      || (__INST(handleType) == @symbol(filePointer))
  4309 
  4419      || (__INST(handleType) == @symbol(socketFilePointer))
  4310     if (fp == nil) {
  4420      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4311         error = @symbol(errorNotOpen);
  4421         if ((fp = __INST(handle)) == nil) {
  4312         goto out;
  4422             error = @symbol(errorNotOpen);
  4313     }
  4423         } else {
  4314         
  4424             FILEPOINTER f = __FILEVal(fp);
  4315     if (__INST(handleType) == @symbol(socketHandle)) {
  4425             int rslt;
  4316         SOCKET sock = __FILEVal(fp);
  4426 
  4317 
  4427             // whether the fclose() will be successful or not - the handle is invalid now!
  4318         if (@global(FileOpenTrace) == true) {
  4428             __INST(handle) = nil;
  4319             fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", sock);
  4429 
  4320         }
  4430             if (@global(FileOpenTrace) == true) {
  4321 
  4431                 fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f);
  4322         // whether the close() will be successful or not - the handle is invalid now!
  4432             }
  4323         __INST(handle) = nil;
       
  4324         do {
  4433 #ifdef WIN32
  4325 #ifdef WIN32
  4434             if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) {
  4326             rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock);
  4435                 // do a fflush() first, so that fclose() doesn't block
  4327 #else
  4436                 // we suspect, that EINTR causes problems in fclose()
  4328             rslt = close(sock);
  4437                 do {
  4329 #endif
  4438                     __threadErrno = 0;
  4330         } while((rslt < 0) && (__threadErrno == EINTR));
  4439                     rslt = __STX_C_CALL1("fflush", fflush, f);
  4331     } else if ((__INST(handleType) == nil)
  4440                 } while((rslt < 0) && (__threadErrno == EINTR));
  4332                || (__INST(handleType) == @symbol(filePointer))
  4441             }
  4333                || (__INST(handleType) == @symbol(socketFilePointer))
       
  4334                || (__INST(handleType) == @symbol(pipeFilePointer)))
       
  4335     {
       
  4336         FILEPOINTER f = __FILEVal(fp);
       
  4337 
       
  4338         if (@global(FileOpenTrace) == true) {
       
  4339             fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", f);
       
  4340         }
       
  4341         // whether the close() will be successful or not - the handle is invalid now!
       
  4342         __INST(handle) = nil;
       
  4343 
       
  4344 #ifdef WIN32
       
  4345         if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) {
       
  4346             // do a fflush() first, so that fclose() doesn't block
       
  4347             // we suspect, that EINTR causes problems in fclose()
  4442             do {
  4348             do {
  4443                 __threadErrno = 0;
  4349                 __threadErrno = 0;
  4444                 rslt = __STX_C_NOINT_CALL1("fclose", fclose, f);
  4350                 rslt = __STX_C_CALL1("fflush", fflush, f);
  4445             } while((rslt < 0) && (__threadErrno == EINTR));
  4351             } while((rslt < 0) && (__threadErrno == EINTR));
       
  4352         }
       
  4353         do {
       
  4354             __threadErrno = 0;
       
  4355             rslt = __STX_C_NOINT_CALL1("fclose", fclose, f);
       
  4356         } while((rslt < 0) && (__threadErrno == EINTR));
  4446 #else
  4357 #else
  4447             __BEGIN_INTERRUPTABLE__
  4358         __BEGIN_INTERRUPTABLE__
  4448             rslt = fclose(f);
  4359         rslt = fclose(f);
  4449             __END_INTERRUPTABLE__
  4360         __END_INTERRUPTABLE__
  4450 #endif
  4361 #endif
  4451             if (rslt < 0) {
  4362     } else {
  4452                 error = __mkSmallInteger(__threadErrno);
  4363         error = @symbol(badHandleType);
  4453                 goto out;
  4364         goto out;
  4454             }
       
  4455         }
       
  4456         RETURN (self);
       
  4457     }
  4365     }
       
  4366 
       
  4367     if (rslt < 0) {
       
  4368         error = __mkSmallInteger(__threadErrno);
       
  4369         goto out;
       
  4370     }
       
  4371     RETURN (self);
       
  4372 
  4458 out:;
  4373 out:;
  4459 %}.
  4374 %}.
  4460 
  4375 
  4461     error notNil ifTrue:[
  4376     error notNil ifTrue:[
  4462         error == #errorNotOpen ifTrue:[
  4377         error == #errorNotOpen ifTrue:[
  4759     self setAccessor:#socketHandle to:something
  4674     self setAccessor:#socketHandle to:something
  4760 ! !
  4675 ! !
  4761 
  4676 
  4762 !ExternalStream methodsFor:'queries'!
  4677 !ExternalStream methodsFor:'queries'!
  4763 
  4678 
  4764 isBinary
  4679 nextError
  4765     "return true, if the stream is in binary (as opposed to text-) mode.
  4680     "return the error by trying to read something.
  4766      The default when created is false."
  4681      Should only be used, when we know, that a read operation
  4767 
  4682      will return an error (otherwise a character may be lost).
  4768     ^ binary
  4683      Return an integer (error number), 0 (EOF) or nil (no error)"
  4769 !
  4684 
  4770 
  4685 %{ /*NOCONTEXT*/
  4771 isBlocking
  4686     FILEPOINTER f;
  4772     "return true, if O_NONBLOCK is NOT set in the fileDescriptor (probably UNIX specific)"
  4687     int ret, _buffered;
       
  4688     OBJ fp;
       
  4689     unsigned char ch;
       
  4690 
       
  4691     if ((__INST(handleType) == nil)
       
  4692      || (__INST(handleType) == @symbol(filePointer))
       
  4693      || (__INST(handleType) == @symbol(socketFilePointer))
       
  4694      || (__INST(handleType) == @symbol(socketHandle))
       
  4695      || (__INST(handleType) == @symbol(pipeFilePointer))) {
       
  4696         if (((fp = __INST(handle)) != nil)
       
  4697             && (__INST(mode) != @symbol(writeonly))
       
  4698         ) {
       
  4699             f = __FILEVal(fp);
       
  4700 
       
  4701             _buffered = (__INST(buffered) == true);
       
  4702             if (_buffered) {
       
  4703                 __READING__(f)
       
  4704             }
       
  4705             __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
       
  4706 
       
  4707             if (ret > 0) {
       
  4708                 RETURN(nil)
       
  4709             }
       
  4710             if (ret < 0) {
       
  4711                 RETURN(__mkSmallInteger(__threadErrno));
       
  4712             } else /* ret == 0 */ {
       
  4713                 RETURN(__mkSmallInteger(0)); /* EOF */
       
  4714             }
       
  4715         }
       
  4716     }
       
  4717 %}.
       
  4718 !
       
  4719 
       
  4720 numAvailable
       
  4721     "return the number of bytes available for reading"
       
  4722 
       
  4723     |fd|
  4773 
  4724 
  4774     handle isNil ifTrue:[^ self errorNotOpen].
  4725     handle isNil ifTrue:[^ self errorNotOpen].
  4775     ^ OperatingSystem isBlockingOn:self fileDescriptor
  4726     mode == #writeonly ifTrue:[^ self errorWriteOnly].
  4776 !
  4727     fd := self fileDescriptor.
  4777 
  4728 
  4778 isExternalStream
  4729 %{
  4779     "return true, if the receiver is some kind of externalStream;
  4730 #ifdef WIN32
  4780      true is returned here - the method redefined from Object."
  4731     int res = 1;
  4781 
  4732     int success = 0;
  4782     ^ true
  4733 
  4783 !
  4734     if (__INST(handleType) == @symbol(socketHandle)) {
  4784 
  4735         success = ioctlsocket((SOCKET)__externalAddressVal(fd), FIONREAD, &res) == 0;
  4785 isOpen
  4736     } else if (__INST(handleType) == @symbol(socketFilePointer)) {
  4786     "return true, if this stream is open"
  4737         success = ioctlsocket((SOCKET)_get_osfhandle(__intVal(fd)), FIONREAD, &res) == 0;
  4787 
  4738     } else if (__INST(handleType) == @symbol(pipeFilePointer)) {
  4788     ^ handle notNil
  4739         success = PeekNamedPipe((HANDLE)_get_osfhandle(__intVal(fd)),0,0,0,&res,0);
  4789 !
  4740     }
  4790 
  4741     if (success) {
  4791 isReadable
  4742         if (__INST(readAhead) != nil) res++;
  4792     "return true, if this stream can be read from"
  4743         RETURN(__mkSmallInteger(res));
  4793 
  4744     }
  4794     ^ (mode ~~ #writeonly)
  4745 #endif
  4795 !
  4746 %}.
  4796 
  4747 
  4797 isWritable
  4748     ^ (readAhead notNil or:[OperatingSystem readCheck:fd]) ifTrue:[1] ifFalse:[0].
  4798     "return true, if this stream can be written to"
  4749 
  4799 
  4750     "Created: / 4.2.1998 / 16:56:01 / cg"
  4800     ^ (mode ~~ #readonly)
  4751     "Modified: / 4.2.1998 / 17:31:11 / cg"
  4801 ! !
  4752 ! !
  4802 
  4753 
  4803 !ExternalStream methodsFor:'reading'!
  4754 !ExternalStream methodsFor:'reading'!
  4804 
  4755 
  4805 next
  4756 next
  4817 
  4768 
  4818     __INST(lastErrorNumber) = nil;
  4769     __INST(lastErrorNumber) = nil;
  4819     if ((__INST(handleType) == nil)
  4770     if ((__INST(handleType) == nil)
  4820      || (__INST(handleType) == @symbol(filePointer))
  4771      || (__INST(handleType) == @symbol(filePointer))
  4821      || (__INST(handleType) == @symbol(socketFilePointer))
  4772      || (__INST(handleType) == @symbol(socketFilePointer))
       
  4773      || (__INST(handleType) == @symbol(socketHandle))
  4822      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4774      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4823 	if (((fp = __INST(handle)) != nil)
  4775         if (((fp = __INST(handle)) != nil)
  4824 	    && (__INST(mode) != @symbol(writeonly))
  4776             && (__INST(mode) != @symbol(writeonly))
  4825 	) {
  4777         ) {
  4826 	    f = __FILEVal(fp);
  4778             f = __FILEVal(fp);
  4827 
  4779 
  4828 	    _buffered = (__INST(buffered) == true);
  4780             _buffered = (__INST(buffered) == true);
  4829 	    if (_buffered) {
  4781             if (_buffered) {
  4830 		__READING__(f)
  4782                 __READING__(f)
  4831 	    }
  4783             }
  4832 	    __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  4784             __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  4833 
  4785 
  4834 	    if (ret > 0) {
  4786             if (ret > 0) {
  4835 		pos = __INST(position);
  4787                 pos = __INST(position);
  4836 		if (__isSmallInteger(pos)) {
  4788                 if (__isSmallInteger(pos)) {
  4837 		    OBJ t;
  4789                     OBJ t;
  4838 
  4790 
  4839 		    t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  4791                     t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  4840 		} else {
  4792                 } else {
  4841 		    __INST(position) = nil; /* i.e. do not know */
  4793                     __INST(position) = nil; /* i.e. do not know */
  4842 		}
  4794                 }
  4843 		if (__INST(binary) == true) {
  4795                 if (__INST(binary) == true) {
  4844 		    RETURN ( __mkSmallInteger(ch) );
  4796                     RETURN ( __mkSmallInteger(ch) );
  4845 		}
  4797                 }
  4846 		RETURN ( __MKCHARACTER(ch) );
  4798                 RETURN ( __MKCHARACTER(ch) );
  4847 	    }
  4799             }
  4848 
  4800 
  4849 	    __INST(position) = nil;
  4801             __INST(position) = nil;
  4850 	    if (ret < 0) {
  4802             if (ret < 0) {
  4851 		error = __mkSmallInteger(__threadErrno);
  4803                 error = __mkSmallInteger(__threadErrno);
  4852 	    } else /* ret == 0 */ {
  4804             } else /* ret == 0 */ {
  4853 		__INST(hitEOF) = true;
  4805                 __INST(hitEOF) = true;
  4854 	    }
  4806             }
  4855 	}
  4807         }
  4856     }
  4808     }
  4857 %}.
  4809 %}.
  4858     hitEOF == true ifTrue:[^ self pastEndRead].
  4810     hitEOF == true ifTrue:[^ self pastEndRead].
  4859     error notNil ifTrue:[
  4811     error notNil ifTrue:[
  4860 	lastErrorNumber := error.
  4812         lastErrorNumber := error.
  4861 	^ self readError:error
  4813         ^ self readError:error
  4862     ].
  4814     ].
  4863     handle isNil ifTrue:[^ self errorNotOpen].
  4815     handle isNil ifTrue:[^ self errorNotOpen].
  4864     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4816     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4865 
  4817 
  4866     readAhead notNil ifTrue:[
  4818     readAhead notNil ifTrue:[
  4867 	c := readAhead.
  4819         c := readAhead.
  4868 	readAhead := nil.
  4820         readAhead := nil.
  4869 	^ c.
  4821         ^ c.
  4870     ].
  4822     ].
  4871     c := self nextByteFromFile:handle.
  4823     c := self nextByteFromFile:handle.
  4872     c isNil ifTrue:[
  4824     c isNil ifTrue:[
  4873 	^ self pastEndRead.
  4825         ^ self pastEndRead.
  4874     ].
  4826     ].
  4875     binary == true ifTrue:[
  4827     binary == true ifTrue:[
  4876 	^ c
  4828         ^ c
  4877     ].
  4829     ].
  4878     ^ Character value:c
  4830     ^ Character value:c
  4879 !
  4831 !
  4880 
  4832 
  4881 next:count
  4833 next:count
  4917 
  4869 
  4918     __INST(lastErrorNumber) = nil;
  4870     __INST(lastErrorNumber) = nil;
  4919     if ((__INST(handleType) == nil)
  4871     if ((__INST(handleType) == nil)
  4920      || (__INST(handleType) == @symbol(filePointer))
  4872      || (__INST(handleType) == @symbol(filePointer))
  4921      || (__INST(handleType) == @symbol(socketFilePointer))
  4873      || (__INST(handleType) == @symbol(socketFilePointer))
       
  4874      || (__INST(handleType) == @symbol(socketHandle))
  4922      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4875      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4923 	if (((fp = __INST(handle)) != nil)
  4876         if (((fp = __INST(handle)) != nil)
  4924 	    && (__INST(mode) != @symbol(writeonly))
  4877             && (__INST(mode) != @symbol(writeonly))
  4925 	) {
  4878         ) {
  4926 	    f = __FILEVal(fp);
  4879             f = __FILEVal(fp);
  4927 
  4880 
  4928 	    _buffered = (__INST(buffered) == true);
  4881             _buffered = (__INST(buffered) == true);
  4929 	    if (_buffered) {
  4882             if (_buffered) {
  4930 		__READING__(f)
  4883                 __READING__(f)
  4931 	    }
  4884             }
  4932 	    __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  4885             __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
  4933 
  4886 
  4934 	    if (ret > 0) {
  4887             if (ret > 0) {
  4935 		pos = __INST(position);
  4888                 pos = __INST(position);
  4936 		if (__isSmallInteger(pos)) {
  4889                 if (__isSmallInteger(pos)) {
  4937 		    OBJ t;
  4890                     OBJ t;
  4938 
  4891 
  4939 		    t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  4892                     t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t);
  4940 		} else {
  4893                 } else {
  4941 		    __INST(position) = nil; /* i.e. do not know */
  4894                     __INST(position) = nil; /* i.e. do not know */
  4942 		}
  4895                 }
  4943 		if (__INST(binary) == true) {
  4896                 if (__INST(binary) == true) {
  4944 		    RETURN ( __mkSmallInteger(ch) );
  4897                     RETURN ( __mkSmallInteger(ch) );
  4945 		}
  4898                 }
  4946 		RETURN ( __MKCHARACTER(ch) );
  4899                 RETURN ( __MKCHARACTER(ch) );
  4947 	    }
  4900             }
  4948 
  4901 
  4949 	    __INST(position) = nil;
  4902             __INST(position) = nil;
  4950 	    if (ret < 0) {
  4903             if (ret < 0) {
  4951 		error = __mkSmallInteger(__threadErrno);
  4904                 error = __mkSmallInteger(__threadErrno);
  4952 	    } else /* ret == 0 */ {
  4905             } else /* ret == 0 */ {
  4953 		__INST(hitEOF) = true;
  4906                 __INST(hitEOF) = true;
  4954 	    }
  4907             }
  4955 	}
  4908         }
  4956     }
  4909     }
  4957 %}.
  4910 %}.
  4958     hitEOF == true ifTrue:[^ nil].
  4911     hitEOF == true ifTrue:[^ nil].
  4959     error notNil ifTrue:[
  4912     error notNil ifTrue:[
  4960 	lastErrorNumber := error.
  4913         lastErrorNumber := error.
  4961 	^ self readError:error.
  4914         ^ self readError:error.
  4962     ].
  4915     ].
  4963     handle isNil ifTrue:[^ self errorNotOpen].
  4916     handle isNil ifTrue:[^ self errorNotOpen].
  4964     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4917     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4965 
  4918 
  4966     readAhead notNil ifTrue:[
  4919     readAhead notNil ifTrue:[
  4967 	c := readAhead.
  4920         c := readAhead.
  4968 	readAhead := nil.
  4921         readAhead := nil.
  4969 	^ c.
  4922         ^ c.
  4970     ].
  4923     ].
  4971     c := self nextByteFromFile:handle.
  4924     c := self nextByteFromFile:handle.
  4972     c isNil ifTrue:[
  4925     c isNil ifTrue:[
  4973 	^ nil.
  4926         ^ nil.
  4974     ].
  4927     ].
  4975     binary == true ifTrue:[
  4928     binary == true ifTrue:[
  4976 	^ c
  4929         ^ c
  4977     ].
  4930     ].
  4978     ^ Character value:c
  4931     ^ Character value:c
  4979 !
  4932 !
  4980 
  4933 
  4981 peek
  4934 peek
  4991     int ret, _buffered;
  4944     int ret, _buffered;
  4992     OBJ fp;
  4945     OBJ fp;
  4993     OBJ ra;
  4946     OBJ ra;
  4994 
  4947 
  4995     if ((ra = __INST(readAhead)) != nil) {
  4948     if ((ra = __INST(readAhead)) != nil) {
  4996 	if (__INST(binary) == true) {
  4949         if (__INST(binary) == true) {
  4997 	    RETURN ( ra );
  4950             RETURN ( ra );
  4998 	}
  4951         }
  4999 	c = __intVal(ra);
  4952         c = __intVal(ra);
  5000 	RETURN ( __MKCHARACTER(c) );
  4953         RETURN ( __MKCHARACTER(c) );
  5001     }
  4954     }
  5002 
  4955 
  5003     __INST(lastErrorNumber) = nil;
  4956     __INST(lastErrorNumber) = nil;
  5004 
  4957 
  5005     if ((__INST(handleType) == nil)
  4958     if ((__INST(handleType) == nil)
  5006      || (__INST(handleType) == @symbol(filePointer))
  4959      || (__INST(handleType) == @symbol(filePointer))
  5007      || (__INST(handleType) == @symbol(socketFilePointer))
  4960      || (__INST(handleType) == @symbol(socketFilePointer))
       
  4961      || (__INST(handleType) == @symbol(socketHandle))
  5008      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  4962      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5009 	if (((fp = __INST(handle)) != nil)
  4963         if (((fp = __INST(handle)) != nil)
  5010 	    && (__INST(mode) != @symbol(writeonly))
  4964             && (__INST(mode) != @symbol(writeonly))
  5011 	) {
  4965         ) {
  5012 	    f = __FILEVal(fp);
  4966             f = __FILEVal(fp);
  5013 	    _buffered = (__INST(buffered) == true);
  4967             _buffered = (__INST(buffered) == true);
  5014 	    if (_buffered) {
  4968             if (_buffered) {
  5015 		__READING__(f)
  4969                 __READING__(f)
  5016 	    }
  4970             }
  5017 	    __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  4971             __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5018 
  4972 
  5019 	    if (ret > 0) {
  4973             if (ret > 0) {
  5020 		__UNGETC__(c, f, _buffered);
  4974                 __UNGETC__(c, f, _buffered);
  5021 
  4975 
  5022 		if (__INST(binary) == true) {
  4976                 if (__INST(binary) == true) {
  5023 		    RETURN ( __mkSmallInteger(c) );
  4977                     RETURN ( __mkSmallInteger(c) );
  5024 		}
  4978                 }
  5025 		RETURN ( __MKCHARACTER(c) );
  4979                 RETURN ( __MKCHARACTER(c) );
  5026 	    }
  4980             }
  5027 	    if (ret < 0) {
  4981             if (ret < 0) {
  5028 		error = __mkSmallInteger(__threadErrno);
  4982                 error = __mkSmallInteger(__threadErrno);
  5029 	    } else /* ret == 0 */ {
  4983             } else /* ret == 0 */ {
  5030 		__INST(hitEOF) = true;
  4984                 __INST(hitEOF) = true;
  5031 	    }
  4985             }
  5032 	}
  4986         }
  5033     }
  4987     }
  5034 %}.
  4988 %}.
  5035     hitEOF == true ifTrue:[^ self pastEndRead].
  4989     hitEOF == true ifTrue:[^ self pastEndRead].
  5036     error notNil ifTrue:[
  4990     error notNil ifTrue:[
  5037 	lastErrorNumber := error.
  4991         lastErrorNumber := error.
  5038 	^ self readError:error.
  4992         ^ self readError:error.
  5039     ].
  4993     ].
  5040     handle isNil ifTrue:[^ self errorNotOpen].
  4994     handle isNil ifTrue:[^ self errorNotOpen].
  5041     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  4995     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5042 
  4996 
  5043     readAhead isNil ifTrue:[
  4997     readAhead isNil ifTrue:[
  5044 	readAhead := self nextOrNil.
  4998         readAhead := self nextOrNil.
  5045 	readAhead isNil ifTrue:[
  4999         readAhead isNil ifTrue:[
  5046 	    ^ self pastEndRead.
  5000             ^ self pastEndRead.
  5047 	].
  5001         ].
  5048     ].
  5002     ].
  5049     ^ readAhead
  5003     ^ readAhead
  5050 !
  5004 !
  5051 
  5005 
  5052 peekOrNil
  5006 peekOrNil
  5062     int ret, _buffered;
  5016     int ret, _buffered;
  5063     OBJ fp;
  5017     OBJ fp;
  5064     OBJ ra;
  5018     OBJ ra;
  5065 
  5019 
  5066     if ((ra = __INST(readAhead)) != nil) {
  5020     if ((ra = __INST(readAhead)) != nil) {
  5067 	if (__INST(binary) == true) {
  5021         if (__INST(binary) == true) {
  5068 	    RETURN ( ra );
  5022             RETURN ( ra );
  5069 	}
  5023         }
  5070 	c = __intVal(ra);
  5024         c = __intVal(ra);
  5071 	RETURN ( __MKCHARACTER(c) );
  5025         RETURN ( __MKCHARACTER(c) );
  5072     }
  5026     }
  5073 
  5027 
  5074     __INST(lastErrorNumber) = nil;
  5028     __INST(lastErrorNumber) = nil;
  5075 
  5029 
  5076     if ((__INST(handleType) == nil)
  5030     if ((__INST(handleType) == nil)
  5077      || (__INST(handleType) == @symbol(filePointer))
  5031      || (__INST(handleType) == @symbol(filePointer))
  5078      || (__INST(handleType) == @symbol(socketFilePointer))
  5032      || (__INST(handleType) == @symbol(socketFilePointer))
       
  5033      || (__INST(handleType) == @symbol(socketHandle))
  5079      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5034      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5080 	if (((fp = __INST(handle)) != nil)
  5035         if (((fp = __INST(handle)) != nil)
  5081 	    && (__INST(mode) != @symbol(writeonly))
  5036             && (__INST(mode) != @symbol(writeonly))
  5082 	) {
  5037         ) {
  5083 	    f = __FILEVal(fp);
  5038             f = __FILEVal(fp);
  5084 	    _buffered = (__INST(buffered) == true);
  5039             _buffered = (__INST(buffered) == true);
  5085 	    if (_buffered) {
  5040             if (_buffered) {
  5086 		__READING__(f)
  5041                 __READING__(f)
  5087 	    }
  5042             }
  5088 	    __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5043             __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5089 
  5044 
  5090 	    if (ret > 0) {
  5045             if (ret > 0) {
  5091 		__UNGETC__(c, f, _buffered);
  5046                 __UNGETC__(c, f, _buffered);
  5092 
  5047 
  5093 		if (__INST(binary) == true) {
  5048                 if (__INST(binary) == true) {
  5094 		    RETURN ( __mkSmallInteger(c) );
  5049                     RETURN ( __mkSmallInteger(c) );
  5095 		}
  5050                 }
  5096 		RETURN ( __MKCHARACTER(c) );
  5051                 RETURN ( __MKCHARACTER(c) );
  5097 	    }
  5052             }
  5098 	    if (ret < 0) {
  5053             if (ret < 0) {
  5099 		error = __mkSmallInteger(__threadErrno);
  5054                 error = __mkSmallInteger(__threadErrno);
  5100 	    } else /* ret == 0 */ {
  5055             } else /* ret == 0 */ {
  5101 		__INST(hitEOF) = true;
  5056                 __INST(hitEOF) = true;
  5102 	    }
  5057             }
  5103 	}
  5058         }
  5104     }
  5059     }
  5105 %}.
  5060 %}.
  5106     hitEOF == true ifTrue:[^ nil].
  5061     hitEOF == true ifTrue:[^ nil].
  5107     error notNil ifTrue:[
  5062     error notNil ifTrue:[
  5108 	lastErrorNumber := error.
  5063         lastErrorNumber := error.
  5109 	^ self readError:error.
  5064         ^ self readError:error.
  5110     ].
  5065     ].
  5111     handle isNil ifTrue:[^ self errorNotOpen].
  5066     handle isNil ifTrue:[^ self errorNotOpen].
  5112     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5067     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
  5113 
  5068 
  5114     readAhead isNil ifTrue:[
  5069     readAhead isNil ifTrue:[
  5115 	readAhead := self nextOrNil.
  5070         readAhead := self nextOrNil.
  5116     ].
  5071     ].
  5117     ^ readAhead
  5072     ^ readAhead
  5118 !
  5073 !
  5119 
  5074 
  5120 upToEnd
  5075 upToEnd
  5176     OBJ fp, pos, lim;
  5131     OBJ fp, pos, lim;
  5177     char c;
  5132     char c;
  5178     int ret, _buffered;
  5133     int ret, _buffered;
  5179 
  5134 
  5180     if (__INST(hitEOF) == true) {
  5135     if (__INST(hitEOF) == true) {
  5181 	RETURN (true);
  5136         RETURN (true);
  5182     }
  5137     }
  5183     pos = __INST(position);
  5138     pos = __INST(position);
  5184     lim = __INST(readLimit);
  5139     lim = __INST(readLimit);
  5185     if (lim != nil) {
  5140     if (lim != nil) {
  5186 	off_t _pos, _readLimit;
  5141         off_t _pos, _readLimit;
  5187 
  5142 
  5188 	_pos = __signedLongIntVal(pos);
  5143         _pos = __signedLongIntVal(pos);
  5189 	_pos = _pos - __intVal( @global(PositionableStream:ZeroPosition)) + 1;
  5144         _pos = _pos - __intVal( @global(PositionableStream:ZeroPosition)) + 1;
  5190 	_readLimit = __signedLongIntVal(lim);
  5145         _readLimit = __signedLongIntVal(lim);
  5191 	if (_pos > _readLimit) {
  5146         if (_pos > _readLimit) {
  5192 	    RETURN (true);
  5147             RETURN (true);
  5193 	}
  5148         }
  5194     }
  5149     }
  5195 
  5150 
  5196     __INST(lastErrorNumber) = nil;
  5151     __INST(lastErrorNumber) = nil;
  5197 
  5152 
  5198     if ((__INST(handleType) == nil)
  5153     if ((__INST(handleType) == nil)
  5199      || (__INST(handleType) == @symbol(filePointer))
  5154      || (__INST(handleType) == @symbol(filePointer))
  5200      || (__INST(handleType) == @symbol(socketFilePointer))
  5155      || (__INST(handleType) == @symbol(socketFilePointer))
       
  5156      || (__INST(handleType) == @symbol(socketHandle))
  5201      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5157      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5202 	if ((fp = __INST(handle)) != nil) {
  5158         if ((fp = __INST(handle)) != nil) {
  5203 	    f = __FILEVal(fp);
  5159             f = __FILEVal(fp);
  5204 	    if (_buffered = (__INST(buffered) == true)) {
  5160             if (_buffered = (__INST(buffered) == true)) {
  5205 		__READING__(f);
  5161                 __READING__(f);
  5206 	    } else {
  5162             } else {
  5207 		if (__INST(readAhead) != nil) {
  5163                 if (__INST(readAhead) != nil) {
  5208 		    RETURN (false);
  5164                     RETURN (false);
  5209 		}
  5165                 }
  5210 	    }
  5166             }
  5211 
  5167 
  5212 	    /*
  5168             /*
  5213 	     * read ahead ...
  5169              * read ahead ...
  5214 	     */
  5170              */
  5215 	    do {
  5171             do {
  5216 #ifdef WIN32
  5172 #ifdef WIN32
  5217 # if 1
  5173 # if 1
  5218 		__READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5174                 __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5219 
  5175 
  5220 # else
  5176 # else
  5221 		__BEGIN_INTERRUPTABLE__
  5177                 __BEGIN_INTERRUPTABLE__
  5222 		__READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5178                 __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5223 		__END_INTERRUPTABLE__
  5179                 __END_INTERRUPTABLE__
  5224 # endif
  5180 # endif
  5225 #else /* not WIN32 */
  5181 #else /* not WIN32 */
  5226 		__BEGIN_INTERRUPTABLE__
  5182                 __BEGIN_INTERRUPTABLE__
  5227 		__READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5183                 __READBYTE__(ret, f, &c, _buffered, __INST(handleType));
  5228 		__END_INTERRUPTABLE__
  5184                 __END_INTERRUPTABLE__
  5229 #endif
  5185 #endif
  5230 	    } while ((ret < 0) && (__threadErrno == EINTR));
  5186             } while ((ret < 0) && (__threadErrno == EINTR));
  5231 
  5187 
  5232 #if defined(WIN32) && defined(EPIPE)
  5188 #if defined(WIN32) && defined(EPIPE)
  5233 	    if (ret < 0) {
  5189             if (ret < 0) {
  5234 		if (__threadErrno == EPIPE) {
  5190                 if (__threadErrno == EPIPE) {
  5235 		    ret = 0;
  5191                     ret = 0;
  5236 		    __threadErrno = 0;
  5192                     __threadErrno = 0;
  5237 		}
  5193                 }
  5238 		if (__threadErrno == 0) {
  5194                 if (__threadErrno == 0) {
  5239 		    ret = 0;   /* how comes ? */
  5195                     ret = 0;   /* how comes ? */
  5240 		}
  5196                 }
  5241 	    }
  5197             }
  5242 #endif
  5198 #endif
  5243 	    if (ret > 0) {
  5199             if (ret > 0) {
  5244 		__UNGETC__(c&0xff, f, _buffered);
  5200                 __UNGETC__(c&0xff, f, _buffered);
  5245 		RETURN (false);
  5201                 RETURN (false);
  5246 	    }
  5202             }
  5247 
  5203 
  5248 	    if (ret == 0) {
  5204             if (ret == 0) {
  5249 		__INST(hitEOF) = true;
  5205                 __INST(hitEOF) = true;
  5250 		RETURN (true);
  5206                 RETURN (true);
  5251 	    }
  5207             }
  5252 
  5208 
  5253 	    /* ret < 0 */
  5209             /* ret < 0 */
  5254 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5210             __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5255 	}
  5211         }
  5256     }
  5212     }
  5257 %}.
  5213 %}.
  5258     lastErrorNumber notNil ifTrue:[^ self readError].
  5214     lastErrorNumber notNil ifTrue:[^ self readError].
  5259     handle isNil ifTrue:[^ self errorNotOpen].
  5215     handle isNil ifTrue:[^ self errorNotOpen].
  5260     mode == #writeonly ifTrue:[^ self errorWriteOnly].
  5216     mode == #writeonly ifTrue:[^ self errorWriteOnly].
  5261     readAhead notNil ifTrue:[^ false].
  5217     readAhead notNil ifTrue:[^ false].
  5262 
  5218 
  5263     "/ migration support
  5219     "/ migration support
  5264     ^ self
  5220     ^ self
  5265 	atEndFile:handle
  5221         atEndFile:handle
  5266 
  5222 
  5267     "Modified: / 30.10.1998 / 20:16:06 / cg"
  5223     "Modified: / 30.10.1998 / 20:16:06 / cg"
  5268 !
  5224 !
  5269 
  5225 
  5270 canReadWithoutBlocking
  5226 canReadWithoutBlocking
  5271     "return true, if any data is available for reading (i.e.
  5227     "return true, if any data is available for reading (i.e.
  5272      a read operation will not block the smalltalk process), false otherwise."
  5228      a read operation will not block the smalltalk process), false otherwise.
  5273 
  5229      We know, that error conditions do not block, so return true for errors."
  5274     |fd|
  5230 
  5275 
  5231     ^ readAhead notNil
  5276     readAhead notNil ifTrue:[^ true].
  5232 	or:[handle isNil]
  5277     handle isNil ifTrue:[^ self errorNotOpen].
  5233 	or:[mode == #writeonly
  5278     mode == #writeonly ifTrue:[^ self errorWriteOnly].
  5234 	or:[OperatingSystem readCheck:self fileDescriptor]]
  5279 
       
  5280     fd := self fileDescriptor.
       
  5281     ^ OperatingSystem readCheck:fd
       
  5282 
  5235 
  5283     "
  5236     "
  5284      |pipe|
  5237      |pipe|
  5285 
  5238 
  5286      pipe := PipeStream readingFrom:'(sleep 10; echo hello)'.
  5239      pipe := PipeStream readingFrom:'(sleep 10; echo hello)'.
  5295     "Modified: 25.9.1997 / 13:08:45 / stefan"
  5248     "Modified: 25.9.1997 / 13:08:45 / stefan"
  5296 !
  5249 !
  5297 
  5250 
  5298 canWriteWithoutBlocking
  5251 canWriteWithoutBlocking
  5299     "return true, if data can be written into the stream
  5252     "return true, if data can be written into the stream
  5300      (i.e. a write operation will not block the smalltalk process)."
  5253      (i.e. a write operation will not block the smalltalk process).
  5301 
  5254      We know, that error conditions do not block, so return true for errors."
  5302     |fd|
  5255 
  5303 
  5256     ^ handle isNil
  5304     handle isNil ifTrue:[^ self errorNotOpen].
  5257 	or:[mode == #readonly
  5305     mode == #readonly ifTrue:[^ self errorReadOnly].
  5258 	or:[OperatingSystem writeCheck:self fileDescriptor]]
  5306 
       
  5307     fd := self fileDescriptor.
       
  5308     ^ OperatingSystem writeCheck:fd
       
  5309 !
  5259 !
  5310 
  5260 
  5311 gotErrorOrEOF
  5261 gotErrorOrEOF
  5312     "answerv true, if amn error or eof has been occured on the stream"
  5262     "answerv true, if amn error or eof has been occured on the stream"
  5313 
  5263 
  5314     ^ hitEOF == true or:[lastErrorNumber notNil]
  5264     ^ hitEOF == true or:[lastErrorNumber notNil]
  5315 !
  5265 !
  5316 
  5266 
  5317 nextError
  5267 isBinary
  5318     "return the error by trying to read something.
  5268     "return true, if the stream is in binary (as opposed to text-) mode.
  5319      Should only be used, when we know, that a read operation
  5269      The default when created is false."
  5320      will return an error (otherwise a character may be lost).
  5270 
  5321      Return an integer (error number), 0 (EOF) or nil (no error)"
  5271     ^ binary
  5322 
  5272 !
  5323 %{ /*NOCONTEXT*/
  5273 
  5324     FILEPOINTER f;
  5274 isBlocking
  5325     int ret, _buffered;
  5275     "return true, if O_NONBLOCK is NOT set in the fileDescriptor (probably UNIX specific)"
  5326     OBJ fp;
       
  5327     unsigned char ch;
       
  5328 
       
  5329     if ((__INST(handleType) == nil)
       
  5330      || (__INST(handleType) == @symbol(filePointer))
       
  5331      || (__INST(handleType) == @symbol(socketFilePointer))
       
  5332      || (__INST(handleType) == @symbol(pipeFilePointer))) {
       
  5333 	if (((fp = __INST(handle)) != nil)
       
  5334 	    && (__INST(mode) != @symbol(writeonly))
       
  5335 	) {
       
  5336 	    f = __FILEVal(fp);
       
  5337 
       
  5338 	    _buffered = (__INST(buffered) == true);
       
  5339 	    if (_buffered) {
       
  5340 		__READING__(f)
       
  5341 	    }
       
  5342 	    __READBYTE__(ret, f, &ch, _buffered, __INST(handleType));
       
  5343 
       
  5344 	    if (ret > 0) {
       
  5345 		RETURN(nil)
       
  5346 	    }
       
  5347 	    if (ret < 0) {
       
  5348 		RETURN(__mkSmallInteger(__threadErrno));
       
  5349 	    } else /* ret == 0 */ {
       
  5350 		RETURN(__mkSmallInteger(0)); /* EOF */
       
  5351 	    }
       
  5352 	}
       
  5353     }
       
  5354 %}.
       
  5355 !
       
  5356 
       
  5357 numAvailable
       
  5358     "return the number of bytes available for reading"
       
  5359 
       
  5360     |fd|
       
  5361 
  5276 
  5362     handle isNil ifTrue:[^ self errorNotOpen].
  5277     handle isNil ifTrue:[^ self errorNotOpen].
  5363     mode == #writeonly ifTrue:[^ self errorWriteOnly].
  5278     ^ OperatingSystem isBlockingOn:self fileDescriptor
  5364 
  5279 !
  5365     fd := self fileDescriptor.
  5280 
  5366     ^ OperatingSystem numAvailableForReadOn:fd.
  5281 isExternalStream
  5367 
  5282     "return true, if the receiver is some kind of externalStream;
  5368 "/    self atEnd ifTrue:[^ 0].
  5283      true is returned here - the method redefined from Object."
  5369 "/    self canReadWithoutBlocking ifTrue:[
  5284 
  5370 "/        ^ 1
  5285     ^ true
  5371 "/    ].
  5286 !
  5372 "/    ^ 0
  5287 
  5373 
  5288 isOpen
  5374     "Created: / 4.2.1998 / 16:56:01 / cg"
  5289     "return true, if this stream is open"
  5375     "Modified: / 4.2.1998 / 17:31:11 / cg"
  5290 
       
  5291     ^ handle notNil
       
  5292 !
       
  5293 
       
  5294 isReadable
       
  5295     "return true, if this stream can be read from"
       
  5296 
       
  5297     ^ (mode ~~ #writeonly)
       
  5298 !
       
  5299 
       
  5300 isWritable
       
  5301     "return true, if this stream can be written to"
       
  5302 
       
  5303     ^ (mode ~~ #readonly)
  5376 ! !
  5304 ! !
  5377 
  5305 
  5378 !ExternalStream methodsFor:'waiting for I/O'!
  5306 !ExternalStream methodsFor:'waiting for I/O'!
  5379 
  5307 
  5380 canBeSelected
  5308 canBeSelected
  5514     OBJ fp;
  5442     OBJ fp;
  5515     char *cp;
  5443     char *cp;
  5516 
  5444 
  5517     if ((__INST(handleType) == nil)
  5445     if ((__INST(handleType) == nil)
  5518      || (__INST(handleType) == @symbol(filePointer))
  5446      || (__INST(handleType) == @symbol(filePointer))
       
  5447      || (__INST(handleType) == @symbol(socketHandle))
  5519      || (__INST(handleType) == @symbol(socketFilePointer))
  5448      || (__INST(handleType) == @symbol(socketFilePointer))
  5520      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5449      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5521 	__INST(lastErrorNumber) = nil;
  5450         __INST(lastErrorNumber) = nil;
  5522 	if (((fp = __INST(handle)) != nil)
  5451         if (((fp = __INST(handle)) != nil)
  5523 	    && (__INST(mode) != @symbol(readonly))
  5452             && (__INST(mode) != @symbol(readonly))
  5524 	    && (__INST(binary) != true)
  5453             && (__INST(binary) != true)
  5525 	) {
  5454         ) {
  5526 	    f = __FILEVal(fp);
  5455             f = __FILEVal(fp);
  5527 
  5456 
  5528 	    if (_buffered = (__INST(buffered) == true)) {
  5457             if (_buffered = (__INST(buffered) == true)) {
  5529 		__WRITING__(f)
  5458                 __WRITING__(f)
  5530 	    }
  5459             }
  5531 	    {
  5460             {
  5532 		OBJ mode = __INST(eolMode);
  5461                 OBJ mode = __INST(eolMode);
  5533 
  5462 
  5534 		if (mode == @symbol(cr)) {
  5463                 if (mode == @symbol(cr)) {
  5535 		    cp = "\r"; len = 1;
  5464                     cp = "\r"; len = 1;
  5536 		} else if (mode == @symbol(crlf)) {
  5465                 } else if (mode == @symbol(crlf)) {
  5537 		    cp = "\r\n"; len = 2;
  5466                     cp = "\r\n"; len = 2;
  5538 		} else {
  5467                 } else {
  5539 		    cp = "\n"; len = 1;
  5468                     cp = "\n"; len = 1;
  5540 		}
  5469                 }
  5541 	    }
  5470             }
  5542 #ifdef WIN32
  5471 #ifdef WIN32
  5543 	    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5472             if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5544 		cnt = __win32_fwrite(cp, 1, len, f);
  5473                 cnt = __win32_fwrite(cp, 1, len, f);
  5545 	    } else
  5474             } else
  5546 #endif
  5475 #endif
  5547 	    {
  5476             {
  5548 		__WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType));
  5477                 __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType));
  5549 	    }
  5478             }
  5550 	    if (cnt == len) {
  5479             if (cnt == len) {
  5551 		if (__isSmallInteger(__INST(position))) {
  5480                 if (__isSmallInteger(__INST(position))) {
  5552 		    INT np = __intVal(__INST(position)) + len;
  5481                     INT np = __intVal(__INST(position)) + len;
  5553 		    OBJ t;
  5482                     OBJ t;
  5554 
  5483 
  5555 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5484                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5556 		} else {
  5485                 } else {
  5557 		    __INST(position) = nil; /* i.e: dont know */
  5486                     __INST(position) = nil; /* i.e: dont know */
  5558 		}
  5487                 }
  5559 		RETURN ( self );
  5488                 RETURN ( self );
  5560 	    }
  5489             }
  5561 	    __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5490             __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
  5562 	}
  5491         }
  5563     }
  5492     }
  5564 %}.
  5493 %}.
  5565     lastErrorNumber notNil ifTrue:[self writeError. ^ self].
  5494     lastErrorNumber notNil ifTrue:[self writeError. ^ self].
  5566     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5495     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5567     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5496     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5626 
  5555 
  5627     __INST(lastErrorNumber) = nil;
  5556     __INST(lastErrorNumber) = nil;
  5628     if ((__INST(handleType) == nil)
  5557     if ((__INST(handleType) == nil)
  5629      || (__INST(handleType) == @symbol(filePointer))
  5558      || (__INST(handleType) == @symbol(filePointer))
  5630      || (__INST(handleType) == @symbol(socketFilePointer))
  5559      || (__INST(handleType) == @symbol(socketFilePointer))
       
  5560      || (__INST(handleType) == @symbol(socketHandle))
  5631      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5561      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5632 	if (((fp = __INST(handle)) != nil)
  5562         if (((fp = __INST(handle)) != nil)
  5633 	    && (__INST(mode) != @symbol(readonly))
  5563             && (__INST(mode) != @symbol(readonly))
  5634 	) {
  5564         ) {
  5635 	    if (__INST(binary) != true) {
  5565             if (__INST(binary) != true) {
  5636 		if (__isCharacter(aCharacter)) {
  5566                 if (__isCharacter(aCharacter)) {
  5637 		    codePoint = __intVal(__characterVal(aCharacter));
  5567                     codePoint = __intVal(__characterVal(aCharacter));
  5638 		    if (codePoint <= 0xFF) {
  5568                     if (codePoint <= 0xFF) {
  5639 			c = codePoint;
  5569                         c = codePoint;
  5640     doWrite:
  5570     doWrite:
  5641 			f = __FILEVal(fp);
  5571                         f = __FILEVal(fp);
  5642 			if (! f) {
  5572                         if (! f) {
  5643 			    fprintf(stderr, "oops - fileHandle is NULL in nextPut:\n");
  5573                             fprintf(stderr, "oops - fileHandle is NULL in nextPut:\n");
  5644 			    __INST(handle) = nil;
  5574                             __INST(handle) = nil;
  5645 			    goto out;
  5575                             goto out;
  5646 			}
  5576                         }
  5647 
  5577 
  5648 			if (_buffered = (__INST(buffered) == true)) {
  5578                         if (_buffered = (__INST(buffered) == true)) {
  5649 			    __WRITING__(f)
  5579                             __WRITING__(f)
  5650 			}
  5580                         }
  5651 #ifdef WIN32
  5581 #ifdef WIN32
  5652 			if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5582                         if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5653 			    cnt = __win32_fwrite(&c, 1, 1, f);
  5583                             cnt = __win32_fwrite(&c, 1, 1, f);
  5654 			} else
  5584                         } else
  5655 #endif
  5585 #endif
  5656 			__WRITEBYTE__(cnt, f, &c, _buffered, __INST(handleType));
  5586                         __WRITEBYTE__(cnt, f, &c, _buffered, __INST(handleType));
  5657 			if (cnt == 1) {
  5587                         if (cnt == 1) {
  5658 			    if (__isSmallInteger(__INST(position))) {
  5588                             if (__isSmallInteger(__INST(position))) {
  5659 				INT np = __intVal(__INST(position)) + 1;
  5589                                 INT np = __intVal(__INST(position)) + 1;
  5660 				OBJ t;
  5590                                 OBJ t;
  5661 
  5591 
  5662 				t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5592                                 t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5663 			    } else {
  5593                             } else {
  5664 				__INST(position) = nil; /* i.e. do not know */
  5594                                 __INST(position) = nil; /* i.e. do not know */
  5665 			    }
  5595                             }
  5666 			    RETURN ( self );
  5596                             RETURN ( self );
  5667 			}
  5597                         }
  5668 			error = __mkSmallInteger(__threadErrno);
  5598                         error = __mkSmallInteger(__threadErrno);
  5669 		    }
  5599                     }
  5670 		}
  5600                 }
  5671 	    } else {
  5601             } else {
  5672 		if (__isSmallInteger(aCharacter)) {
  5602                 if (__isSmallInteger(aCharacter)) {
  5673 		    c = __intVal(aCharacter);
  5603                     c = __intVal(aCharacter);
  5674 		    goto doWrite;
  5604                     goto doWrite;
  5675 		}
  5605                 }
  5676 	    }
  5606             }
  5677 	}
  5607         }
  5678     }
  5608     }
  5679 out: ;
  5609 out: ;
  5680 %}.
  5610 %}.
  5681     error notNil ifTrue:[
  5611     error notNil ifTrue:[
  5682 	lastErrorNumber := error.
  5612         lastErrorNumber := error.
  5683 	self writeError:error.
  5613         self writeError:error.
  5684 	^ self
  5614         ^ self
  5685     ].
  5615     ].
  5686     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5616     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5687     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5617     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5688     binary == true ifFalse:[
  5618     binary == true ifFalse:[
  5689 	(aCharacter isCharacter not
  5619         (aCharacter isCharacter not
  5690 	or:[aCharacter codePoint > 16rFF]) ifTrue:[
  5620         or:[aCharacter codePoint > 16rFF]) ifTrue:[
  5691 	    self argumentMustBeCharacter.
  5621             self argumentMustBeCharacter.
  5692 	    ^ self.
  5622             ^ self.
  5693 	].
  5623         ].
  5694     ] ifTrue:[
  5624     ] ifTrue:[
  5695 	aCharacter isInteger ifFalse:[
  5625         aCharacter isInteger ifFalse:[
  5696 	    self argumentMustBeInteger.
  5626             self argumentMustBeInteger.
  5697 	    ^ self.
  5627             ^ self.
  5698 	].
  5628         ].
  5699     ].
  5629     ].
  5700     "/ migration support
  5630     "/ migration support
  5701     self
  5631     self
  5702 	nextPutByte:aCharacter asInteger
  5632         nextPutByte:aCharacter asInteger
  5703 	toFile:handle
  5633         toFile:handle
  5704 !
  5634 !
  5705 
  5635 
  5706 nextPutAll:aCollection
  5636 nextPutAll:aCollection
  5707     "write all elements of the argument, aCollection.
  5637     "write all elements of the argument, aCollection.
  5708      Reimplemented for speed when writing strings or byteArrays.
  5638      Reimplemented for speed when writing strings or byteArrays.
  5719     __INST(lastErrorNumber) = nil;
  5649     __INST(lastErrorNumber) = nil;
  5720 
  5650 
  5721     if ((__INST(handleType) == nil)
  5651     if ((__INST(handleType) == nil)
  5722      || (__INST(handleType) == @symbol(filePointer))
  5652      || (__INST(handleType) == @symbol(filePointer))
  5723      || (__INST(handleType) == @symbol(socketFilePointer))
  5653      || (__INST(handleType) == @symbol(socketFilePointer))
       
  5654      || (__INST(handleType) == @symbol(socketHandle))
  5724      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5655      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5725 	if (((fp = __INST(handle)) != nil)
  5656         if (((fp = __INST(handle)) != nil)
  5726 	    && (__INST(mode) != @symbol(readonly))
  5657             && (__INST(mode) != @symbol(readonly))
  5727 	) {
  5658         ) {
  5728 	    f = __FILEVal(fp);
  5659             f = __FILEVal(fp);
  5729 	    if (! f) {
  5660             if (! f) {
  5730 		fprintf(stderr, "oops - fileHandle is NULL in nextPutAll:\n");
  5661                 fprintf(stderr, "oops - fileHandle is NULL in nextPutAll:\n");
  5731 		__INST(handle) = nil;
  5662                 __INST(handle) = nil;
  5732 		goto out;
  5663                 goto out;
  5733 	    }
  5664             }
  5734 	    if (_buffered = (__INST(buffered) == true)) {
  5665             if (_buffered = (__INST(buffered) == true)) {
  5735 		__WRITING__(f)
  5666                 __WRITING__(f)
  5736 	    }
  5667             }
  5737 
  5668 
  5738 	    if (__isStringLike(aCollection)) {
  5669             if (__isStringLike(aCollection)) {
  5739 		len = __stringSize(aCollection);
  5670                 len = __stringSize(aCollection);
  5740 #ifdef WIN32
  5671 #ifdef WIN32
  5741 		if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5672                 if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5742 		    cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f);
  5673                     cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f);
  5743 		} else
  5674                 } else
  5744 #endif
  5675 #endif
  5745 		{
  5676                 {
  5746 		    o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
  5677                     o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
  5747 		    __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
  5678                     __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
  5748 		}
  5679                 }
  5749 	    } else {
  5680             } else {
  5750 		if (__INST(binary) == true) {
  5681                 if (__INST(binary) == true) {
  5751 		    INT offs;
  5682                     INT offs;
  5752 
  5683 
  5753 		    if (__isByteArrayLike(aCollection)) {
  5684                     if (__isByteArrayLike(aCollection)) {
  5754 			offs = 0;
  5685                         offs = 0;
  5755 			len = __byteArraySize(aCollection);
  5686                         len = __byteArraySize(aCollection);
  5756 		    } else if (__isBytes(aCollection)) {
  5687                     } else if (__isBytes(aCollection)) {
  5757 			offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars));
  5688                         offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars));
  5758 			len = __byteArraySize(aCollection) - offs;
  5689                         len = __byteArraySize(aCollection) - offs;
  5759 		    } else
  5690                     } else
  5760 			goto out;
  5691                         goto out;
  5761 #ifdef WIN32
  5692 #ifdef WIN32
  5762 		    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5693                     if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5763 			cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f);
  5694                         cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f);
  5764 		    } else
  5695                     } else
  5765 #endif
  5696 #endif
  5766 		    {
  5697                     {
  5767 			o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element) - (char *)__InstPtr(aCollection);
  5698                         o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element) - (char *)__InstPtr(aCollection);
  5768 			o_offs += offs;
  5699                         o_offs += offs;
  5769 			__WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
  5700                         __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType));
  5770 		    }
  5701                     }
  5771 		} else
  5702                 } else
  5772 		    goto out;
  5703                     goto out;
  5773 	    }
  5704             }
  5774 
  5705 
  5775 	    if (cnt == len) {
  5706             if (cnt == len) {
  5776 		if (__isSmallInteger(__INST(position))) {
  5707                 if (__isSmallInteger(__INST(position))) {
  5777 		    INT np = __intVal(__INST(position)) + len;
  5708                     INT np = __intVal(__INST(position)) + len;
  5778 		    OBJ t;
  5709                     OBJ t;
  5779 
  5710 
  5780 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5711                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5781 		} else {
  5712                 } else {
  5782 		    __INST(position) = nil; /* i.e. do not know */
  5713                     __INST(position) = nil; /* i.e. do not know */
  5783 		}
  5714                 }
  5784 		RETURN (self);
  5715                 RETURN (self);
  5785 	    }
  5716             }
  5786 	    error = __mkSmallInteger(__threadErrno);
  5717             error = __mkSmallInteger(__threadErrno);
  5787 	}
  5718         }
  5788     }
  5719     }
  5789 out: ;
  5720 out: ;
  5790 %}.
  5721 %}.
  5791     error notNil ifTrue:[
  5722     error notNil ifTrue:[
  5792 	lastErrorNumber := error.
  5723         lastErrorNumber := error.
  5793 	self writeError:error.
  5724         self writeError:error.
  5794 	^ self
  5725         ^ self
  5795     ].
  5726     ].
  5796     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5727     handle isNil ifTrue:[self errorNotOpen. ^ self].
  5797     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5728     (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
  5798 
  5729 
  5799     ^ super nextPutAll:aCollection
  5730     ^ super nextPutAll:aCollection
  5814 
  5745 
  5815     __INST(lastErrorNumber) = nil;
  5746     __INST(lastErrorNumber) = nil;
  5816     if ((__INST(handleType) == nil)
  5747     if ((__INST(handleType) == nil)
  5817      || (__INST(handleType) == @symbol(filePointer))
  5748      || (__INST(handleType) == @symbol(filePointer))
  5818      || (__INST(handleType) == @symbol(socketFilePointer))
  5749      || (__INST(handleType) == @symbol(socketFilePointer))
       
  5750      || (__INST(handleType) == @symbol(socketHandle))
  5819      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5751      || (__INST(handleType) == @symbol(pipeFilePointer))) {
  5820 	if (((fp = __INST(handle)) != nil)
  5752         if (((fp = __INST(handle)) != nil)
  5821 	    && (__INST(mode) != @symbol(readonly))
  5753             && (__INST(mode) != @symbol(readonly))
  5822 	    && __bothSmallInteger(start, stop)
  5754             && __bothSmallInteger(start, stop)
  5823 	) {
  5755         ) {
  5824 	    f = __FILEVal(fp);
  5756             f = __FILEVal(fp);
  5825 	    if (_buffered = (__INST(buffered) == true)) {
  5757             if (_buffered = (__INST(buffered) == true)) {
  5826 		__WRITING__(f)
  5758                 __WRITING__(f)
  5827 	    }
  5759             }
  5828 	    iStart = __intVal(start);
  5760             iStart = __intVal(start);
  5829 	    iStop = __intVal(stop);
  5761             iStop = __intVal(stop);
  5830 	    if ((iStart < 1) || (iStop < iStart)) {
  5762             if ((iStart < 1) || (iStop < iStart)) {
  5831 		RETURN(self);
  5763                 RETURN(self);
  5832 	    }
  5764             }
  5833 	    if (__isStringLike(aCollection)) {
  5765             if (__isStringLike(aCollection)) {
  5834 		len = __stringSize(aCollection);
  5766                 len = __stringSize(aCollection);
  5835 		if (iStop > len) {
  5767                 if (iStop > len) {
  5836 		    RETURN(self);
  5768                     RETURN(self);
  5837 		}
  5769                 }
  5838 		if (iStop > len)
  5770                 if (iStop > len)
  5839 		    iStop = len;
  5771                     iStop = len;
  5840 		len = iStop - iStart + 1;
  5772                 len = iStop - iStart + 1;
  5841 #ifdef WIN32
  5773 #ifdef WIN32
  5842 		if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5774                 if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5843 		    cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f);
  5775                     cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f);
  5844 		} else
  5776                 } else
  5845 #endif
  5777 #endif
  5846 		{
  5778                 {
  5847 		    o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
  5779                     o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection);
  5848 		    __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+iStart-1, len, _buffered, __INST(handleType));
  5780                     __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+iStart-1, len, _buffered, __INST(handleType));
  5849 		}
  5781                 }
  5850 	    } else {
  5782             } else {
  5851 		if (__INST(binary) == true) {
  5783                 if (__INST(binary) == true) {
  5852 		    int offs;
  5784                     int offs;
  5853 
  5785 
  5854 		    if (__isByteArrayLike(aCollection)) {
  5786                     if (__isByteArrayLike(aCollection)) {
  5855 			offs = 0;
  5787                         offs = 0;
  5856 			len = __byteArraySize(aCollection);
  5788                         len = __byteArraySize(aCollection);
  5857 		    } else if (__isBytes(aCollection)) {
  5789                     } else if (__isBytes(aCollection)) {
  5858 			offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars));
  5790                         offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars));
  5859 			len = __byteArraySize(aCollection) - offs;
  5791                         len = __byteArraySize(aCollection) - offs;
  5860 		    } else
  5792                     } else
  5861 			goto out;
  5793                         goto out;
  5862 
  5794 
  5863 		    if (iStop > len) {
  5795                     if (iStop > len) {
  5864 			RETURN(self);
  5796                         RETURN(self);
  5865 		    }
  5797                     }
  5866 		    if (iStop > len)
  5798                     if (iStop > len)
  5867 			iStop = len;
  5799                         iStop = len;
  5868 		    len = iStop - iStart + 1;
  5800                     len = iStop - iStart + 1;
  5869 		    offs += iStart - 1;
  5801                     offs += iStart - 1;
  5870 #ifdef WIN32
  5802 #ifdef WIN32
  5871 		    if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5803                     if ((f == __win32_stdout()) || (f == __win32_stderr())) {
  5872 			cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f);
  5804                         cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f);
  5873 		    } else
  5805                     } else
  5874 #endif
  5806 #endif
  5875 		    {
  5807                     {
  5876 			o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element)-(char *)__InstPtr(aCollection);
  5808                         o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element)-(char *)__InstPtr(aCollection);
  5877 			__WRITEBYTES_OBJ__(cnt, f,  aCollection, o_offs+offs, len, _buffered, __INST(handleType));
  5809                         __WRITEBYTES_OBJ__(cnt, f,  aCollection, o_offs+offs, len, _buffered, __INST(handleType));
  5878 		    }
  5810                     }
  5879 		} else
  5811                 } else
  5880 		    goto out;
  5812                     goto out;
  5881 	    }
  5813             }
  5882 	    if (cnt == len) {
  5814             if (cnt == len) {
  5883 		if (__isSmallInteger(__INST(position))) {
  5815                 if (__isSmallInteger(__INST(position))) {
  5884 		    INT np = __intVal(__INST(position)) + len;
  5816                     INT np = __intVal(__INST(position)) + len;
  5885 		    OBJ t;
  5817                     OBJ t;
  5886 
  5818 
  5887 		    t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5819                     t = __MKINT(np); __INST(position) = t; __STORE(self, t);
  5888 		} else {
  5820                 } else {
  5889 		    __INST(position) = nil; /* i.e. do not know */
  5821                     __INST(position) = nil; /* i.e. do not know */
  5890 		}
  5822                 }
  5891 		RETURN (self);
  5823                 RETURN (self);
  5892 	    }
  5824             }
  5893 	    error = __mkSmallInteger(__threadErrno);
  5825             error = __mkSmallInteger(__threadErrno);
  5894 	}
  5826         }
  5895     }
  5827     }
  5896 out: ;
  5828 out: ;
  5897 %}.
  5829 %}.
  5898     error notNil ifTrue:[
  5830     error notNil ifTrue:[
  5899 	lastErrorNumber := error.
  5831         lastErrorNumber := error.
  5900 	self writeError:error.
  5832         self writeError:error.
  5901 	^ self
  5833         ^ self
  5902     ].
  5834     ].
  5903     ^ super nextPutAll:aCollection startingAt:start to:stop
  5835     ^ super nextPutAll:aCollection startingAt:start to:stop
  5904 !
  5836 !
  5905 
  5837 
  5906 nextPutAllUnicode:aString
  5838 nextPutAllUnicode:aString
  5956 ! !
  5888 ! !
  5957 
  5889 
  5958 !ExternalStream class methodsFor:'documentation'!
  5890 !ExternalStream class methodsFor:'documentation'!
  5959 
  5891 
  5960 version
  5892 version
  5961     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.384 2014-04-09 21:10:05 stefan Exp $'
  5893     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.385 2014-04-18 13:06:29 stefan Exp $'
  5962 !
  5894 !
  5963 
  5895 
  5964 version_CVS
  5896 version_CVS
  5965     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.384 2014-04-09 21:10:05 stefan Exp $'
  5897     ^ '$Header: /cvs/stx/stx/libbasic/ExternalStream.st,v 1.385 2014-04-18 13:06:29 stefan Exp $'
  5966 ! !
  5898 ! !
  5967 
  5899 
  5968 
  5900 
  5969 ExternalStream initialize!
  5901 ExternalStream initialize!