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