changeset 23032 | 3555c5883830 |
parent 22978 | 589f146aebcd |
child 23110 | 6c43a792029a |
23031:9baa6604dedb | 23032:3555c5883830 |
---|---|
1 "{ Encoding: utf8 }" |
1 "{ Encoding: utf8 }" |
2 |
2 |
3 " |
3 " |
4 COPYRIGHT (c) 1988 by Claus Gittinger |
4 COPYRIGHT (c) 1988 by Claus Gittinger |
5 All Rights Reserved |
5 All Rights Reserved |
6 |
6 |
7 This software is furnished under a license and may be used |
7 This software is furnished under a license and may be used |
8 only in accordance with the terms of that license and with the |
8 only in accordance with the terms of that license and with the |
9 inclusion of the above copyright notice. This software may not |
9 inclusion of the above copyright notice. This software may not |
10 be provided or otherwise made available to, or used by, any |
10 be provided or otherwise made available to, or used by, any |
204 #ifdef DEBUGGING |
204 #ifdef DEBUGGING |
205 extern char *__survStartPtr, *__survEndPtr; |
205 extern char *__survStartPtr, *__survEndPtr; |
206 # define DEBUGBUFFER(buf) \ |
206 # define DEBUGBUFFER(buf) \ |
207 if (((char *)(buf) >= __survStartPtr) \ |
207 if (((char *)(buf) >= __survStartPtr) \ |
208 && ((char *)(buf) < __survEndPtr)) { \ |
208 && ((char *)(buf) < __survEndPtr)) { \ |
209 __fatal0("read into survivor\n"); \ |
209 __fatal0("read into survivor\n"); \ |
210 } |
210 } |
211 |
211 |
212 #else |
212 #else |
213 # define DEBUGBUFFER(buf) /* nothing */ |
213 # define DEBUGBUFFER(buf) /* nothing */ |
214 #endif |
214 #endif |
225 # define OPT_FSEEK(f, pos, whence) /* nothing */ |
225 # define OPT_FSEEK(f, pos, whence) /* nothing */ |
226 #endif |
226 #endif |
227 |
227 |
228 #ifdef __win32__ |
228 #ifdef __win32__ |
229 # define READ(ret, f, cp, n, handleType) { \ |
229 # define READ(ret, f, cp, n, handleType) { \ |
230 if (handleType == @symbol(socketHandle)) { \ |
230 if (handleType == @symbol(socketHandle)) { \ |
231 (ret) = __STX_WSA_NOINT_CALL4("recv", recv, (f), (cp), (n), 0); \ |
231 (ret) = __STX_WSA_NOINT_CALL4("recv", recv, (f), (cp), (n), 0); \ |
232 } else { \ |
232 } else { \ |
233 HANDLE h = _get_osfhandle(fileno(f)); \ |
233 HANDLE h = _get_osfhandle(fileno(f)); \ |
234 if (handleType == @symbol(socketFilePointer)) { \ |
234 if (handleType == @symbol(socketFilePointer)) { \ |
235 (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\ |
235 (ret) = __STX_WSA_NOINT_CALL4("recv", recv, h, (cp), (n), 0);\ |
236 } else { \ |
236 } else { \ |
237 int __res; \ |
237 int __res; \ |
238 (ret) = __STX_API_NOINT_CALL5("ReadFile", ReadFile, h, (cp), (n), &__res, 0);\ |
238 (ret) = __STX_API_NOINT_CALL5("ReadFile", ReadFile, h, (cp), (n), &__res, 0);\ |
239 (ret) = (ret) > 0 ? __res : (__threadErrno == __WIN32_ERR(ERROR_BROKEN_PIPE) ? 0 : -1); \ |
239 (ret) = (ret) > 0 ? __res : (__threadErrno == __WIN32_ERR(ERROR_BROKEN_PIPE) ? 0 : -1); \ |
240 } \ |
240 } \ |
241 } \ |
241 } \ |
242 } |
242 } |
243 |
243 |
244 # define WRITE(ret, f, cp, n, handleType) { \ |
244 # define WRITE(ret, f, cp, n, handleType) { \ |
245 if (handleType == @symbol(socketHandle)) { \ |
245 if (handleType == @symbol(socketHandle)) { \ |
246 (ret) = __STX_WSA_NOINT_CALL4("send", send, (f), (cp), (n), 0); \ |
246 (ret) = __STX_WSA_NOINT_CALL4("send", send, (f), (cp), (n), 0); \ |
247 } else {\ |
247 } else {\ |
248 HANDLE h = _get_osfhandle(fileno(f)); \ |
248 HANDLE h = _get_osfhandle(fileno(f)); \ |
249 if (handleType == @symbol(socketFilePointer)) { \ |
249 if (handleType == @symbol(socketFilePointer)) { \ |
250 (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\ |
250 (ret) = __STX_WSA_NOINT_CALL4("send", send, h, (cp), (n), 0);\ |
251 } else {\ |
251 } else {\ |
252 int __res; \ |
252 int __res; \ |
253 (ret) = __STX_API_NOINT_CALL5("WriteFile", WriteFile, h, (cp), (n), &__res, 0);\ |
253 (ret) = __STX_API_NOINT_CALL5("WriteFile", WriteFile, h, (cp), (n), &__res, 0);\ |
254 (ret) = (ret) ? __res : -1; \ |
254 (ret) = (ret) ? __res : -1; \ |
255 } \ |
255 } \ |
256 } \ |
256 } \ |
257 } |
257 } |
258 |
258 |
259 # define FFLUSH(fp) fflush(fp) |
259 # define FFLUSH(fp) fflush(fp) |
260 # undef STDIO_NEEDS_FSEEK |
260 # undef STDIO_NEEDS_FSEEK |
261 # define FILEPOINTER FILE * |
261 # define FILEPOINTER FILE * |
262 # define FILENO(f) fileno(f) |
262 # define FILENO(f) fileno(f) |
263 |
263 |
264 # define __READING__(f) \ |
264 # define __READING__(f) \ |
265 if ((__INST(didWrite) != false) \ |
265 if ((__INST(didWrite) != false) \ |
266 && (__INST(mode) == @symbol(readwrite))) { \ |
266 && (__INST(mode) == @symbol(readwrite))) { \ |
267 __INST(didWrite) = false; \ |
267 __INST(didWrite) = false; \ |
268 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
268 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
269 } |
269 } |
270 |
270 |
271 # define __WRITING__(f) \ |
271 # define __WRITING__(f) \ |
272 if ((__INST(didWrite) != true) \ |
272 if ((__INST(didWrite) != true) \ |
273 && (__INST(mode) == @symbol(readwrite))) { \ |
273 && (__INST(mode) == @symbol(readwrite))) { \ |
274 __INST(didWrite) = true; \ |
274 __INST(didWrite) = true; \ |
275 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
275 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
276 } |
276 } |
277 |
277 |
278 # define __UNGETC__(c, f, isBuffered) \ |
278 # define __UNGETC__(c, f, isBuffered) \ |
279 if (isBuffered) { \ |
279 if (isBuffered) { \ |
280 ungetc((c), (f)); \ |
280 ungetc((c), (f)); \ |
281 } else { \ |
281 } else { \ |
282 __INST(readAhead) = __mkSmallInteger((c)); \ |
282 __INST(readAhead) = __mkSmallInteger((c)); \ |
283 } |
283 } |
284 |
284 |
285 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \ |
285 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \ |
286 if (isBuffered) { \ |
286 if (isBuffered) { \ |
287 for (;;) { \ |
287 for (;;) { \ |
288 CLEAR_ERRNO; \ |
288 CLEAR_ERRNO; \ |
289 (ret) = getc(f); \ |
289 (ret) = getc(f); \ |
290 if ((ret) >= 0) { \ |
290 if ((ret) >= 0) { \ |
291 *(buf) = (ret); \ |
291 *(buf) = (ret); \ |
292 (ret) = 1; \ |
292 (ret) = 1; \ |
293 } else if (ferror(f)) { \ |
293 } else if (ferror(f)) { \ |
294 if (__threadErrno == EINTR) { \ |
294 if (__threadErrno == EINTR) { \ |
295 clearerr(f); \ |
295 clearerr(f); \ |
296 continue; \ |
296 continue; \ |
297 } \ |
297 } \ |
298 } else { \ |
298 } else { \ |
299 (ret) = 0; \ |
299 (ret) = 0; \ |
300 } \ |
300 } \ |
301 break; \ |
301 break; \ |
302 } \ |
302 } \ |
303 } else { \ |
303 } else { \ |
304 OBJ rA = __INST(readAhead); \ |
304 OBJ rA = __INST(readAhead); \ |
305 if (rA != nil) { \ |
305 if (rA != nil) { \ |
306 *(buf) = (char)__intVal(rA); \ |
306 *(buf) = (char)__intVal(rA); \ |
307 __INST(readAhead) = nil; \ |
307 __INST(readAhead) = nil; \ |
308 (ret) = 1; \ |
308 (ret) = 1; \ |
309 } else { \ |
309 } else { \ |
310 for (;;) { \ |
310 for (;;) { \ |
311 CLEAR_ERRNO; \ |
311 CLEAR_ERRNO; \ |
312 READ((ret), f, buf, 1, handleType); \ |
312 READ((ret), f, buf, 1, handleType); \ |
313 if ((ret) >= 0 || __threadErrno != EINTR) \ |
313 if ((ret) >= 0 || __threadErrno != EINTR) \ |
314 break; \ |
314 break; \ |
315 } \ |
315 } \ |
316 } \ |
316 } \ |
317 } |
317 } |
318 |
318 |
319 /* |
319 /* |
320 * read_bytes into a c-buffer |
320 * read_bytes into a c-buffer |
321 * (which may NOT move) |
321 * (which may NOT move) |
322 */ |
322 */ |
323 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
323 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
324 (ret) = 0; \ |
324 (ret) = 0; \ |
325 if (isBuffered) { \ |
325 if (isBuffered) { \ |
326 int __offs = 0; \ |
326 int __offs = 0; \ |
327 while (__offs < (cnt)) { \ |
327 while (__offs < (cnt)) { \ |
328 CLEAR_ERRNO; \ |
328 CLEAR_ERRNO; \ |
329 (ret) = getc(f); \ |
329 (ret) = getc(f); \ |
330 if ((ret) < 0) { \ |
330 if ((ret) < 0) { \ |
331 if (ferror(f)) { \ |
331 if (ferror(f)) { \ |
332 if (__threadErrno == EINTR) { \ |
332 if (__threadErrno == EINTR) { \ |
333 clearerr(f); \ |
333 clearerr(f); \ |
334 continue; \ |
334 continue; \ |
335 } \ |
335 } \ |
336 } else { \ |
336 } else { \ |
337 (ret) = 0; \ |
337 (ret) = 0; \ |
338 } \ |
338 } \ |
339 break; \ |
339 break; \ |
340 } \ |
340 } \ |
341 (buf)[__offs++] = (ret); \ |
341 (buf)[__offs++] = (ret); \ |
342 } \ |
342 } \ |
343 if (__offs > 0) \ |
343 if (__offs > 0) \ |
344 (ret) = __offs; \ |
344 (ret) = __offs; \ |
345 } else { \ |
345 } else { \ |
346 int __offs = 0; \ |
346 int __offs = 0; \ |
347 \ |
347 \ |
348 while (__offs < (cnt)) { \ |
348 while (__offs < (cnt)) { \ |
349 OBJ rA = __INST(readAhead); \ |
349 OBJ rA = __INST(readAhead); \ |
350 if (rA != nil) { \ |
350 if (rA != nil) { \ |
351 (buf)[__offs] = __intVal(rA); \ |
351 (buf)[__offs] = __intVal(rA); \ |
352 __INST(readAhead) = nil; \ |
352 __INST(readAhead) = nil; \ |
353 (ret) = 1; \ |
353 (ret) = 1; \ |
354 } else { \ |
354 } else { \ |
355 CLEAR_ERRNO; \ |
355 CLEAR_ERRNO; \ |
356 READ((ret), f, (buf)+__offs, (cnt)-__offs, handleType); \ |
356 READ((ret), f, (buf)+__offs, (cnt)-__offs, handleType); \ |
357 if ((ret) <= 0) { \ |
357 if ((ret) <= 0) { \ |
358 if ((ret) < 0 && __threadErrno == EINTR) { \ |
358 if ((ret) < 0 && __threadErrno == EINTR) { \ |
359 continue; \ |
359 continue; \ |
360 } \ |
360 } \ |
361 break; \ |
361 break; \ |
362 } \ |
362 } \ |
363 } \ |
363 } \ |
364 __offs += (ret); \ |
364 __offs += (ret); \ |
365 } \ |
365 } \ |
366 if (__offs > 0) \ |
366 if (__offs > 0) \ |
367 (ret) = __offs; \ |
367 (ret) = __offs; \ |
368 } |
368 } |
369 |
369 |
370 # define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
370 # define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
371 { \ |
371 { \ |
372 int __offs = 0; \ |
372 int __offs = 0; \ |
373 int oldFlags; \ |
373 int oldFlags; \ |
374 \ |
374 \ |
375 (ret) = 0; \ |
375 (ret) = 0; \ |
376 if (isBuffered) { \ |
376 if (isBuffered) { \ |
377 while (__offs < (cnt)) { \ |
377 while (__offs < (cnt)) { \ |
378 CLEAR_ERRNO; \ |
378 CLEAR_ERRNO; \ |
379 (ret) = getc(f); \ |
379 (ret) = getc(f); \ |
380 if ((ret) < 0) { \ |
380 if ((ret) < 0) { \ |
381 if (ferror(f)) { \ |
381 if (ferror(f)) { \ |
382 if (__threadErrno == EINTR) { \ |
382 if (__threadErrno == EINTR) { \ |
383 clearerr(f); \ |
383 clearerr(f); \ |
384 continue; \ |
384 continue; \ |
385 } \ |
385 } \ |
386 } else { \ |
386 } else { \ |
387 (ret) = 0; \ |
387 (ret) = 0; \ |
388 } \ |
388 } \ |
389 break; \ |
389 break; \ |
390 } \ |
390 } \ |
391 (buf)[__offs++] = (ret); \ |
391 (buf)[__offs++] = (ret); \ |
392 } \ |
392 } \ |
393 if (__offs > 0) \ |
393 if (__offs > 0) \ |
394 (ret) = __offs; \ |
394 (ret) = __offs; \ |
395 } else { \ |
395 } else { \ |
396 while (__offs < (cnt)) { \ |
396 while (__offs < (cnt)) { \ |
397 OBJ rA = __INST(readAhead); \ |
397 OBJ rA = __INST(readAhead); \ |
398 if (rA != nil) { \ |
398 if (rA != nil) { \ |
399 (buf)[__offs] = __intVal(rA); \ |
399 (buf)[__offs] = __intVal(rA); \ |
400 __INST(readAhead) = nil; \ |
400 __INST(readAhead) = nil; \ |
401 (ret) = 1; \ |
401 (ret) = 1; \ |
402 __offs ++; \ |
402 __offs ++; \ |
403 continue; \ |
403 continue; \ |
404 } \ |
404 } \ |
405 CLEAR_ERRNO; \ |
405 CLEAR_ERRNO; \ |
406 { \ |
406 { \ |
407 int res = -1, ok = 0; \ |
407 int res = -1, ok = 0; \ |
408 SOCKET sock = 0; \ |
408 SOCKET sock = 0; \ |
409 if ((handleType == @symbol(socketFilePointer) && ((ok = ioctlsocket(sock = (SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res) == 0), 1)) \ |
409 if ((handleType == @symbol(socketFilePointer) && ((ok = ioctlsocket(sock = (SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res) == 0), 1)) \ |
410 || (handleType == @symbol(socketHandle) && ((ok = ioctlsocket(sock = (SOCKET)(f), FIONREAD, &res) == 0), 1)) \ |
410 || (handleType == @symbol(socketHandle) && ((ok = ioctlsocket(sock = (SOCKET)(f), FIONREAD, &res) == 0), 1)) \ |
411 || (handleType == @symbol(pipeFilePointer) && ((ok = PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)), 1))) { \ |
411 || (handleType == @symbol(pipeFilePointer) && ((ok = PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)), 1))) { \ |
412 if (!ok) { \ |
412 if (!ok) { \ |
413 __threadErrno = sock ? WSAGetLastError() : __WIN32_ERR(GetLastError()); \ |
413 __threadErrno = sock ? WSAGetLastError() : __WIN32_ERR(GetLastError()); \ |
414 (ret) = __threadErrno == __WIN32_ERR(ERROR_BROKEN_PIPE) ? 0 : -1; \ |
414 (ret) = __threadErrno == __WIN32_ERR(ERROR_BROKEN_PIPE) ? 0 : -1; \ |
415 break; \ |
415 break; \ |
416 } \ |
416 } \ |
417 if (res > 0) { \ |
417 if (res > 0) { \ |
418 if (res > ((cnt)-__offs)) \ |
418 if (res > ((cnt)-__offs)) \ |
419 res = (cnt)-__offs; \ |
419 res = (cnt)-__offs; \ |
420 READ((ret), f, (buf)+__offs, res, handleType); \ |
420 READ((ret), f, (buf)+__offs, res, handleType); \ |
421 } else { \ |
421 } else { \ |
422 if (sock && send(sock, NULL, 0, 0) == SOCKET_ERROR) { \ |
422 if (sock && send(sock, NULL, 0, 0) == SOCKET_ERROR) { \ |
423 (ret) = -1; __threadErrno = WSAGetLastError(); \ |
423 (ret) = -1; __threadErrno = WSAGetLastError(); \ |
424 } else { \ |
424 } else { \ |
425 (ret) = 0; \ |
425 (ret) = 0; \ |
426 } \ |
426 } \ |
427 break; \ |
427 break; \ |
428 } \ |
428 } \ |
429 } else { \ |
429 } else { \ |
430 READ((ret), f, (buf)+__offs, (cnt)-__offs, handleType); \ |
430 READ((ret), f, (buf)+__offs, (cnt)-__offs, handleType); \ |
431 } \ |
431 } \ |
432 } \ |
432 } \ |
433 if ((ret) <= 0) { \ |
433 if ((ret) <= 0) { \ |
434 if ((ret) < 0 && __threadErrno == EINTR)\ |
434 if ((ret) < 0 && __threadErrno == EINTR)\ |
435 continue; \ |
435 continue; \ |
436 break; \ |
436 break; \ |
437 } \ |
437 } \ |
438 __offs += (ret); \ |
438 __offs += (ret); \ |
439 } \ |
439 } \ |
440 if (__offs > 0) \ |
440 if (__offs > 0) \ |
441 (ret) = __offs; \ |
441 (ret) = __offs; \ |
442 } \ |
442 } \ |
443 } |
443 } |
444 |
444 |
445 # define IO_BUFFER_SIZE (8*1024) |
445 # define IO_BUFFER_SIZE (8*1024) |
446 |
446 |
447 # define __READBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
447 # define __READBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
448 { \ |
448 { \ |
449 int __ooffs = obj_offs; \ |
449 int __ooffs = obj_offs; \ |
450 int __offs = 0; \ |
450 int __offs = 0; \ |
451 char *buf = (char *)(obj); \ |
451 char *buf = (char *)(obj); \ |
452 \ |
452 \ |
453 (ret) = 0; \ |
453 (ret) = 0; \ |
454 if (isBuffered) { \ |
454 if (isBuffered) { \ |
455 while (__offs < (cnt)) { \ |
455 while (__offs < (cnt)) { \ |
456 CLEAR_ERRNO; \ |
456 CLEAR_ERRNO; \ |
457 (ret) = getc(f); \ |
457 (ret) = getc(f); \ |
458 if ((ret) < 0) { \ |
458 if ((ret) < 0) { \ |
459 if (ferror(f)) { \ |
459 if (ferror(f)) { \ |
460 if (__threadErrno == EINTR) { \ |
460 if (__threadErrno == EINTR) { \ |
461 clearerr(f); \ |
461 clearerr(f); \ |
462 /* refetch */ \ |
462 /* refetch */ \ |
463 buf = (char *)(obj); \ |
463 buf = (char *)(obj); \ |
464 continue; \ |
464 continue; \ |
465 } \ |
465 } \ |
466 } else { \ |
466 } else { \ |
467 (ret) = 0; \ |
467 (ret) = 0; \ |
468 } \ |
468 } \ |
469 break; \ |
469 break; \ |
470 } \ |
470 } \ |
471 (buf)[__ooffs+__offs] = (ret); \ |
471 (buf)[__ooffs+__offs] = (ret); \ |
472 __offs++; \ |
472 __offs++; \ |
473 } \ |
473 } \ |
474 if (__offs > 0) \ |
474 if (__offs > 0) \ |
475 (ret) = __offs; \ |
475 (ret) = __offs; \ |
476 } else { \ |
476 } else { \ |
477 while (__offs < (cnt)) { \ |
477 while (__offs < (cnt)) { \ |
478 char __buf[IO_BUFFER_SIZE]; \ |
478 char __buf[IO_BUFFER_SIZE]; \ |
479 OBJ rA = __INST(readAhead); \ |
479 OBJ rA = __INST(readAhead); \ |
480 if (rA != nil) { \ |
480 if (rA != nil) { \ |
481 (buf)[__ooffs+__offs] = __intVal(rA); \ |
481 (buf)[__ooffs+__offs] = __intVal(rA); \ |
482 __INST(readAhead) = nil; \ |
482 __INST(readAhead) = nil; \ |
483 (ret) = 1; \ |
483 (ret) = 1; \ |
484 } else { \ |
484 } else { \ |
485 int l; \ |
485 int l; \ |
486 CLEAR_ERRNO; \ |
486 CLEAR_ERRNO; \ |
487 l = (cnt)-__offs; \ |
487 l = (cnt)-__offs; \ |
488 if ( l > IO_BUFFER_SIZE) \ |
488 if ( l > IO_BUFFER_SIZE) \ |
489 l = IO_BUFFER_SIZE; \ |
489 l = IO_BUFFER_SIZE; \ |
490 READ((ret),f, __buf, l, handleType); \ |
490 READ((ret),f, __buf, l, handleType); \ |
491 if ((ret) <= 0) { \ |
491 if ((ret) <= 0) { \ |
492 if ((ret) < 0 && __threadErrno == EINTR) { \ |
492 if ((ret) < 0 && __threadErrno == EINTR) { \ |
493 continue; \ |
493 continue; \ |
494 } \ |
494 } \ |
495 break; \ |
495 break; \ |
496 } \ |
496 } \ |
497 } \ |
497 } \ |
498 if ((ret) > 0 ) { \ |
498 if ((ret) > 0 ) { \ |
499 /* refetch */ \ |
499 /* refetch */ \ |
500 buf = (char *)(obj); \ |
500 buf = (char *)(obj); \ |
501 memcpy((buf)+__ooffs+__offs,__buf,(ret)); \ |
501 memcpy((buf)+__ooffs+__offs,__buf,(ret)); \ |
502 __offs += (ret); \ |
502 __offs += (ret); \ |
503 } else { \ |
503 } else { \ |
504 (ret) = 0; \ |
504 (ret) = 0; \ |
505 } \ |
505 } \ |
506 } \ |
506 } \ |
507 if (__offs > 0) \ |
507 if (__offs > 0) \ |
508 (ret) = __offs; \ |
508 (ret) = __offs; \ |
509 } \ |
509 } \ |
510 } |
510 } |
511 |
511 |
512 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
512 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
513 { \ |
513 { \ |
514 int __ooffs = obj_offs; \ |
514 int __ooffs = obj_offs; \ |
515 int __offs = 0; \ |
515 int __offs = 0; \ |
516 char *buf = (char *)(obj); \ |
516 char *buf = (char *)(obj); \ |
517 \ |
517 \ |
518 (ret) = 0; \ |
518 (ret) = 0; \ |
519 if (isBuffered) { \ |
519 if (isBuffered) { \ |
520 while (__offs < (cnt)) { \ |
520 while (__offs < (cnt)) { \ |
521 CLEAR_ERRNO; \ |
521 CLEAR_ERRNO; \ |
522 (ret) = getc(f); \ |
522 (ret) = getc(f); \ |
523 if ((ret) < 0) { \ |
523 if ((ret) < 0) { \ |
524 if (ferror(f)) { \ |
524 if (ferror(f)) { \ |
525 if (__threadErrno == EINTR) { \ |
525 if (__threadErrno == EINTR) { \ |
526 clearerr(f); \ |
526 clearerr(f); \ |
527 /* refetch */ \ |
527 /* refetch */ \ |
528 buf = (char *)(obj); \ |
528 buf = (char *)(obj); \ |
529 continue; \ |
529 continue; \ |
530 } \ |
530 } \ |
531 } else { \ |
531 } else { \ |
532 (ret) = 0; \ |
532 (ret) = 0; \ |
533 } \ |
533 } \ |
534 break; \ |
534 break; \ |
535 } \ |
535 } \ |
536 (buf)[__ooffs+__offs] = (ret); \ |
536 (buf)[__ooffs+__offs] = (ret); \ |
537 __offs++; \ |
537 __offs++; \ |
538 } \ |
538 } \ |
539 if (__offs > 0) \ |
539 if (__offs > 0) \ |
540 (ret) = __offs; \ |
540 (ret) = __offs; \ |
541 } else { \ |
541 } else { \ |
542 while (__offs < (cnt)) { \ |
542 while (__offs < (cnt)) { \ |
543 char __buf[IO_BUFFER_SIZE]; \ |
543 char __buf[IO_BUFFER_SIZE]; \ |
544 OBJ rA = __INST(readAhead); \ |
544 OBJ rA = __INST(readAhead); \ |
545 if (rA != nil) { \ |
545 if (rA != nil) { \ |
546 (buf)[__ooffs+__offs] = __intVal(rA);\ |
546 (buf)[__ooffs+__offs] = __intVal(rA);\ |
547 __INST(readAhead) = nil; \ |
547 __INST(readAhead) = nil; \ |
548 (ret) = 1; \ |
548 (ret) = 1; \ |
549 __offs++; \ |
549 __offs++; \ |
550 continue; \ |
550 continue; \ |
551 } \ |
551 } \ |
552 { \ |
552 { \ |
553 int res = -1, ok = 0; \ |
553 int res = -1, ok = 0; \ |
554 SOCKET sock = 0; \ |
554 SOCKET sock = 0; \ |
555 int l = (cnt)-__offs; \ |
555 int l = (cnt)-__offs; \ |
556 CLEAR_ERRNO; \ |
556 CLEAR_ERRNO; \ |
557 if (l > IO_BUFFER_SIZE) l = IO_BUFFER_SIZE; \ |
557 if (l > IO_BUFFER_SIZE) l = IO_BUFFER_SIZE; \ |
558 if ((handleType == @symbol(socketFilePointer) && ((ok = ioctlsocket(sock = (SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res) == 0), 1)) \ |
558 if ((handleType == @symbol(socketFilePointer) && ((ok = ioctlsocket(sock = (SOCKET)_get_osfhandle(fileno(f)),FIONREAD,&res) == 0), 1)) \ |
559 || (handleType == @symbol(socketHandle) && ((ok = ioctlsocket(sock = (SOCKET)(f), FIONREAD, &res) == 0), 1)) \ |
559 || (handleType == @symbol(socketHandle) && ((ok = ioctlsocket(sock = (SOCKET)(f), FIONREAD, &res) == 0), 1)) \ |
560 || (handleType == @symbol(pipeFilePointer) && ((ok = PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)), 1))) { \ |
560 || (handleType == @symbol(pipeFilePointer) && ((ok = PeekNamedPipe((HANDLE)_get_osfhandle(fileno(f)),0, 0,0,&res,0)), 1))) { \ |
561 if (!ok) { \ |
561 if (!ok) { \ |
562 __threadErrno = sock ? WSAGetLastError() : __WIN32_ERR(GetLastError()); \ |
562 __threadErrno = sock ? WSAGetLastError() : __WIN32_ERR(GetLastError()); \ |
563 (ret) = __threadErrno == __WIN32_ERR(ERROR_BROKEN_PIPE) ? 0 : -1; \ |
563 (ret) = __threadErrno == __WIN32_ERR(ERROR_BROKEN_PIPE) ? 0 : -1; \ |
564 break; \ |
564 break; \ |
565 } \ |
565 } \ |
566 if (res > 0) { \ |
566 if (res > 0) { \ |
567 if (res > l) res = l; \ |
567 if (res > l) res = l; \ |
568 READ((ret), f, __buf, res, handleType); \ |
568 READ((ret), f, __buf, res, handleType); \ |
569 } else { \ |
569 } else { \ |
570 if (sock && send(sock, NULL, 0, 0) == SOCKET_ERROR) { \ |
570 if (sock && send(sock, NULL, 0, 0) == SOCKET_ERROR) { \ |
571 (ret) = -1; __threadErrno = WSAGetLastError(); \ |
571 (ret) = -1; __threadErrno = WSAGetLastError(); \ |
572 } else { \ |
572 } else { \ |
573 (ret) = 0; \ |
573 (ret) = 0; \ |
574 } \ |
574 } \ |
575 break; \ |
575 break; \ |
576 } \ |
576 } \ |
577 } else { \ |
577 } else { \ |
578 READ((ret), f, __buf, l, handleType); \ |
578 READ((ret), f, __buf, l, handleType); \ |
579 } \ |
579 } \ |
580 if ((ret) <= 0) { \ |
580 if ((ret) <= 0) { \ |
581 if ((ret) < 0 && __threadErrno == EINTR) \ |
581 if ((ret) < 0 && __threadErrno == EINTR) \ |
582 continue; \ |
582 continue; \ |
583 break; \ |
583 break; \ |
584 } \ |
584 } \ |
585 } \ |
585 } \ |
586 if ((ret) > 0) { \ |
586 if ((ret) > 0) { \ |
587 buf = (char *)(obj); \ |
587 buf = (char *)(obj); \ |
588 memcpy((buf)+__ooffs+__offs, __buf, (ret)); \ |
588 memcpy((buf)+__ooffs+__offs, __buf, (ret)); \ |
589 __offs += (ret); \ |
589 __offs += (ret); \ |
590 } else { \ |
590 } else { \ |
591 (ret) = 0; \ |
591 (ret) = 0; \ |
592 } \ |
592 } \ |
593 } \ |
593 } \ |
594 if (__offs > 0) \ |
594 if (__offs > 0) \ |
595 (ret) = __offs; \ |
595 (ret) = __offs; \ |
596 } \ |
596 } \ |
597 } |
597 } |
598 |
598 |
599 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType) \ |
599 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType) \ |
600 if (isBuffered) { \ |
600 if (isBuffered) { \ |
601 for (;;) { \ |
601 for (;;) { \ |
602 CLEAR_ERRNO; \ |
602 CLEAR_ERRNO; \ |
603 ret = putc(*(buf), f); \ |
603 ret = putc(*(buf), f); \ |
604 if ((ret) >= 0) { \ |
604 if ((ret) >= 0) { \ |
605 (ret) = 1; \ |
605 (ret) = 1; \ |
606 } else if (ferror(f)) { \ |
606 } else if (ferror(f)) { \ |
607 if (__threadErrno == EINTR) { \ |
607 if (__threadErrno == EINTR) { \ |
608 clearerr(f); \ |
608 clearerr(f); \ |
609 continue; \ |
609 continue; \ |
610 } \ |
610 } \ |
611 } else \ |
611 } else \ |
612 (ret) = 0; \ |
612 (ret) = 0; \ |
613 break; \ |
613 break; \ |
614 } \ |
614 } \ |
615 } else { \ |
615 } else { \ |
616 for (;;) { \ |
616 for (;;) { \ |
617 CLEAR_ERRNO; \ |
617 CLEAR_ERRNO; \ |
618 WRITE(ret,f, buf, 1, handleType); \ |
618 WRITE(ret,f, buf, 1, handleType); \ |
619 if ((ret) >= 0 || __threadErrno != EINTR) \ |
619 if ((ret) >= 0 || __threadErrno != EINTR) \ |
620 break; \ |
620 break; \ |
621 } \ |
621 } \ |
622 } |
622 } |
623 |
623 |
624 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
624 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
625 (ret) = 0; \ |
625 (ret) = 0; \ |
626 if (isBuffered) { \ |
626 if (isBuffered) { \ |
627 int __offs = 0; \ |
627 int __offs = 0; \ |
628 while (__offs < (cnt)) { \ |
628 while (__offs < (cnt)) { \ |
629 CLEAR_ERRNO; \ |
629 CLEAR_ERRNO; \ |
630 (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\ |
630 (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\ |
631 if ((ret) <= 0) { \ |
631 if ((ret) <= 0) { \ |
632 if (ferror(f)) { \ |
632 if (ferror(f)) { \ |
633 if (__threadErrno == EINTR) { \ |
633 if (__threadErrno == EINTR) { \ |
634 clearerr(f); \ |
634 clearerr(f); \ |
635 continue; \ |
635 continue; \ |
636 } \ |
636 } \ |
637 break; \ |
637 break; \ |
638 } else { \ |
638 } else { \ |
639 (ret) = 0; \ |
639 (ret) = 0; \ |
640 } \ |
640 } \ |
641 } \ |
641 } \ |
642 __offs += (ret); \ |
642 __offs += (ret); \ |
643 } \ |
643 } \ |
644 if (__offs > 0) \ |
644 if (__offs > 0) \ |
645 (ret) = __offs; \ |
645 (ret) = __offs; \ |
646 } else { \ |
646 } else { \ |
647 int __offs = 0; \ |
647 int __offs = 0; \ |
648 while (__offs < (cnt)) { \ |
648 while (__offs < (cnt)) { \ |
649 CLEAR_ERRNO; \ |
649 CLEAR_ERRNO; \ |
650 WRITE((ret),f, (buf)+__offs, (cnt)-__offs, handleType); \ |
650 WRITE((ret),f, (buf)+__offs, (cnt)-__offs, handleType); \ |
651 if ((ret) <= 0) { \ |
651 if ((ret) <= 0) { \ |
652 if ((ret) < 0 && __threadErrno == EINTR) { \ |
652 if ((ret) < 0 && __threadErrno == EINTR) { \ |
653 continue; \ |
653 continue; \ |
654 } \ |
654 } \ |
655 break; \ |
655 break; \ |
656 } \ |
656 } \ |
657 __offs += (ret); \ |
657 __offs += (ret); \ |
658 } \ |
658 } \ |
659 if (__offs > 0) \ |
659 if (__offs > 0) \ |
660 (ret) = __offs; \ |
660 (ret) = __offs; \ |
661 } |
661 } |
662 |
662 |
663 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
663 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
664 { \ |
664 { \ |
665 int __ooffs = obj_offs; \ |
665 int __ooffs = obj_offs; \ |
666 int __offs = 0; \ |
666 int __offs = 0; \ |
667 char *buf = (char *)(obj); \ |
667 char *buf = (char *)(obj); \ |
668 \ |
668 \ |
669 (ret) = 0; \ |
669 (ret) = 0; \ |
670 if (isBuffered) { \ |
670 if (isBuffered) { \ |
671 while (__offs < (cnt)) { \ |
671 while (__offs < (cnt)) { \ |
672 CLEAR_ERRNO; \ |
672 CLEAR_ERRNO; \ |
673 ret = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f); \ |
673 ret = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f); \ |
674 if ((ret) <= 0) { \ |
674 if ((ret) <= 0) { \ |
675 if (ferror(f)) { \ |
675 if (ferror(f)) { \ |
676 if (__threadErrno == EINTR) { \ |
676 if (__threadErrno == EINTR) { \ |
677 /* refetch */ \ |
677 /* refetch */ \ |
678 buf = (char *)(obj); \ |
678 buf = (char *)(obj); \ |
679 clearerr(f); \ |
679 clearerr(f); \ |
680 continue; \ |
680 continue; \ |
681 } \ |
681 } \ |
682 break; \ |
682 break; \ |
683 } else { \ |
683 } else { \ |
684 (ret) = 0; \ |
684 (ret) = 0; \ |
685 } \ |
685 } \ |
686 } \ |
686 } \ |
687 __offs += (ret); \ |
687 __offs += (ret); \ |
688 } \ |
688 } \ |
689 if (__offs > 0) \ |
689 if (__offs > 0) \ |
690 (ret) = __offs; \ |
690 (ret) = __offs; \ |
691 } else { \ |
691 } else { \ |
692 while (__offs < (cnt)) { \ |
692 while (__offs < (cnt)) { \ |
693 char __buf[IO_BUFFER_SIZE]; \ |
693 char __buf[IO_BUFFER_SIZE]; \ |
694 int l; \ |
694 int l; \ |
695 CLEAR_ERRNO; \ |
695 CLEAR_ERRNO; \ |
696 l = (cnt)-__offs; \ |
696 l = (cnt)-__offs; \ |
697 if ( l > IO_BUFFER_SIZE) \ |
697 if ( l > IO_BUFFER_SIZE) \ |
698 l = IO_BUFFER_SIZE; \ |
698 l = IO_BUFFER_SIZE; \ |
699 /* refetch */ \ |
699 /* refetch */ \ |
700 buf = (char *)(obj); \ |
700 buf = (char *)(obj); \ |
701 memcpy(__buf,(buf)+__ooffs+__offs,l); \ |
701 memcpy(__buf,(buf)+__ooffs+__offs,l); \ |
702 WRITE(ret,f, __buf, l, handleType); \ |
702 WRITE(ret,f, __buf, l, handleType); \ |
703 if ((ret) <= 0) { \ |
703 if ((ret) <= 0) { \ |
704 if ((ret) < 0 && __threadErrno == EINTR) { \ |
704 if ((ret) < 0 && __threadErrno == EINTR) { \ |
705 continue; \ |
705 continue; \ |
706 } \ |
706 } \ |
707 break; \ |
707 break; \ |
708 } \ |
708 } \ |
709 __offs += (ret); \ |
709 __offs += (ret); \ |
710 } \ |
710 } \ |
711 if (__offs > 0) \ |
711 if (__offs > 0) \ |
712 (ret) = __offs; \ |
712 (ret) = __offs; \ |
713 } \ |
713 } \ |
714 } |
714 } |
715 |
715 |
716 #else /* ! __win32__ */ |
716 #else /* ! __win32__ */ |
717 /* ======================== UNIX / LINUX ====================================================== */ |
717 /* ======================== UNIX / LINUX ====================================================== */ |
718 typedef int SOCKET; |
718 typedef int SOCKET; |
719 |
719 |
720 # define __READING__(f) \ |
720 # define __READING__(f) \ |
721 if ((__INST(didWrite) != false) \ |
721 if ((__INST(didWrite) != false) \ |
722 && (__INST(mode) == @symbol(readwrite))) { \ |
722 && (__INST(mode) == @symbol(readwrite))) { \ |
723 __INST(didWrite) = false; \ |
723 __INST(didWrite) = false; \ |
724 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
724 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
725 } |
725 } |
726 |
726 |
727 # define __WRITING__(f) \ |
727 # define __WRITING__(f) \ |
728 if ((__INST(didWrite) != true) \ |
728 if ((__INST(didWrite) != true) \ |
729 && (__INST(mode) == @symbol(readwrite))) { \ |
729 && (__INST(mode) == @symbol(readwrite))) { \ |
730 __INST(didWrite) = true; \ |
730 __INST(didWrite) = true; \ |
731 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
731 OPT_FSEEK(f, 0L, SEEK_CUR); /* needed in stdio */ \ |
732 } |
732 } |
733 |
733 |
734 |
734 |
735 # ifdef NO_STDIO |
735 # ifdef NO_STDIO |
736 # define __UNGETC__(c, f, isBuffered) \ |
736 # define __UNGETC__(c, f, isBuffered) \ |
737 __INST(readAhead) = __mkSmallInteger((c)); |
737 __INST(readAhead) = __mkSmallInteger((c)); |
738 # else /* use STDIO */ |
738 # else /* use STDIO */ |
739 # define __UNGETC__(c, f, isBuffered) \ |
739 # define __UNGETC__(c, f, isBuffered) \ |
740 if (isBuffered) { \ |
740 if (isBuffered) { \ |
741 ungetc((c), (f)); \ |
741 ungetc((c), (f)); \ |
742 } else { \ |
742 } else { \ |
743 __INST(readAhead) = __mkSmallInteger((c)); \ |
743 __INST(readAhead) = __mkSmallInteger((c)); \ |
744 } |
744 } |
745 # endif /* use STDIO */ |
745 # endif /* use STDIO */ |
746 |
746 |
747 # ifdef NO_STDIO |
747 # ifdef NO_STDIO |
748 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \ |
748 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \ |
749 { \ |
749 { \ |
750 OBJ rA = __INST(readAhead); \ |
750 OBJ rA = __INST(readAhead); \ |
751 if (rA != nil) { \ |
751 if (rA != nil) { \ |
752 *(buf) = __intVal(rA); \ |
752 *(buf) = __intVal(rA); \ |
753 DEBUGBUFFER(buf); \ |
753 DEBUGBUFFER(buf); \ |
754 __INST(readAhead) = nil; \ |
754 __INST(readAhead) = nil; \ |
755 (ret) = 1; \ |
755 (ret) = 1; \ |
756 } else { \ |
756 } else { \ |
757 for (;;) { \ |
757 for (;;) { \ |
758 CLEAR_ERRNO; \ |
758 CLEAR_ERRNO; \ |
759 (ret) = READ(f, buf, 1, handleType); \ |
759 (ret) = READ(f, buf, 1, handleType); \ |
760 DEBUGBUFFER(buf); \ |
760 DEBUGBUFFER(buf); \ |
761 if ((ret) >= 0) break; \ |
761 if ((ret) >= 0) break; \ |
762 if (errno != EINTR) { \ |
762 if (errno != EINTR) { \ |
763 break; \ |
763 break; \ |
764 } \ |
764 } \ |
765 __HANDLE_INTERRUPTS__; \ |
765 __HANDLE_INTERRUPTS__; \ |
766 } \ |
766 } \ |
767 } \ |
767 } \ |
768 } |
768 } |
769 # else /* use STDIO */ |
769 # else /* use STDIO */ |
770 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \ |
770 # define __READBYTE__(ret, f, buf, isBuffered, handleType) \ |
771 if (isBuffered) { \ |
771 if (isBuffered) { \ |
772 for (;;) { \ |
772 for (;;) { \ |
773 CLEAR_ERRNO; \ |
773 CLEAR_ERRNO; \ |
774 (ret) = getc(f); \ |
774 (ret) = getc(f); \ |
775 if ((ret) >= 0) { \ |
775 if ((ret) >= 0) { \ |
776 DEBUGBUFFER(buf); \ |
776 DEBUGBUFFER(buf); \ |
777 *(buf) = (ret); \ |
777 *(buf) = (ret); \ |
778 (ret) = 1; \ |
778 (ret) = 1; \ |
779 } else if (ferror(f)) { \ |
779 } else if (ferror(f)) { \ |
780 if (errno == EINTR) { \ |
780 if (errno == EINTR) { \ |
781 __HANDLE_INTERRUPTS__; \ |
781 __HANDLE_INTERRUPTS__; \ |
782 clearerr(f); \ |
782 clearerr(f); \ |
783 continue; \ |
783 continue; \ |
784 } \ |
784 } \ |
785 } else \ |
785 } else \ |
786 (ret) = 0; \ |
786 (ret) = 0; \ |
787 break; \ |
787 break; \ |
788 } \ |
788 } \ |
789 } else { \ |
789 } else { \ |
790 OBJ rA = __INST(readAhead); \ |
790 OBJ rA = __INST(readAhead); \ |
791 if (rA != nil) { \ |
791 if (rA != nil) { \ |
792 *(buf) = __intVal(rA); \ |
792 *(buf) = __intVal(rA); \ |
793 DEBUGBUFFER(buf); \ |
793 DEBUGBUFFER(buf); \ |
794 __INST(readAhead) = nil; \ |
794 __INST(readAhead) = nil; \ |
795 (ret) = 1; \ |
795 (ret) = 1; \ |
796 } else { \ |
796 } else { \ |
797 for (;;) { \ |
797 for (;;) { \ |
798 CLEAR_ERRNO; \ |
798 CLEAR_ERRNO; \ |
799 (ret) = read(fileno(f), buf, 1); \ |
799 (ret) = read(fileno(f), buf, 1); \ |
800 DEBUGBUFFER(buf); \ |
800 DEBUGBUFFER(buf); \ |
801 if ((ret) >= 0) break; \ |
801 if ((ret) >= 0) break; \ |
802 if (errno != EINTR) { \ |
802 if (errno != EINTR) { \ |
803 break; \ |
803 break; \ |
804 } \ |
804 } \ |
805 __HANDLE_INTERRUPTS__; \ |
805 __HANDLE_INTERRUPTS__; \ |
806 } \ |
806 } \ |
807 } \ |
807 } \ |
808 } |
808 } |
809 # endif /* use STDIO */ |
809 # endif /* use STDIO */ |
810 |
810 |
811 /* |
811 /* |
812 * read_bytes into a c-buffer |
812 * read_bytes into a c-buffer |
813 * (which may NOT move) |
813 * (which may NOT move) |
814 */ |
814 */ |
815 # ifdef NO_STDIO |
815 # ifdef NO_STDIO |
816 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
816 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
817 { \ |
817 { \ |
818 int __offs = 0, __cnt; \ |
818 int __offs = 0, __cnt; \ |
819 \ |
819 \ |
820 while (__offs < (cnt)) { \ |
820 while (__offs < (cnt)) { \ |
821 OBJ rA = __INST(readAhead); \ |
821 OBJ rA = __INST(readAhead); \ |
822 if (rA != nil) { \ |
822 if (rA != nil) { \ |
823 (buf)[__offs] = __intVal(rA); \ |
823 (buf)[__offs] = __intVal(rA); \ |
824 DEBUGBUFFER(buf); \ |
824 DEBUGBUFFER(buf); \ |
825 __INST(readAhead) = nil; \ |
825 __INST(readAhead) = nil; \ |
826 __offs++; \ |
826 __offs++; \ |
827 } else { \ |
827 } else { \ |
828 CLEAR_ERRNO; \ |
828 CLEAR_ERRNO; \ |
829 __cnt = READ(f, (buf)+__offs, (cnt)-__offs, handleType); \ |
829 __cnt = READ(f, (buf)+__offs, (cnt)-__offs, handleType); \ |
830 DEBUGBUFFER(buf); \ |
830 DEBUGBUFFER(buf); \ |
831 if (__cnt <= 0) { \ |
831 if (__cnt <= 0) { \ |
832 if (__cnt < 0 && errno == EINTR) { \ |
832 if (__cnt < 0 && errno == EINTR) { \ |
833 __HANDLE_INTERRUPTS__; \ |
833 __HANDLE_INTERRUPTS__; \ |
834 continue; \ |
834 continue; \ |
835 } \ |
835 } \ |
836 break; \ |
836 break; \ |
837 } \ |
837 } \ |
838 __offs += __cnt; \ |
838 __offs += __cnt; \ |
839 } \ |
839 } \ |
840 } \ |
840 } \ |
841 if (__offs > 0) \ |
841 if (__offs > 0) \ |
842 (ret) = __offs; \ |
842 (ret) = __offs; \ |
843 } |
843 } |
844 # else /* use STDIO */ |
844 # else /* use STDIO */ |
845 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
845 # define __READBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
846 (ret) = 0; \ |
846 (ret) = 0; \ |
847 if (isBuffered) { \ |
847 if (isBuffered) { \ |
848 int __offs = 0; \ |
848 int __offs = 0; \ |
849 while (__offs < (cnt)) { \ |
849 while (__offs < (cnt)) { \ |
850 CLEAR_ERRNO; \ |
850 CLEAR_ERRNO; \ |
851 (ret) = getc(f); \ |
851 (ret) = getc(f); \ |
852 if ((ret) < 0) { \ |
852 if ((ret) < 0) { \ |
853 if (ferror(f)) { \ |
853 if (ferror(f)) { \ |
854 if (errno == EINTR) { \ |
854 if (errno == EINTR) { \ |
855 __HANDLE_INTERRUPTS__; \ |
855 __HANDLE_INTERRUPTS__; \ |
856 clearerr(f); \ |
856 clearerr(f); \ |
857 continue; \ |
857 continue; \ |
858 } \ |
858 } \ |
859 } else { \ |
859 } else { \ |
860 (ret) = 0; \ |
860 (ret) = 0; \ |
861 } \ |
861 } \ |
862 break; \ |
862 break; \ |
863 } \ |
863 } \ |
864 DEBUGBUFFER(buf); \ |
864 DEBUGBUFFER(buf); \ |
865 (buf)[__offs++] = (ret); \ |
865 (buf)[__offs++] = (ret); \ |
866 } \ |
866 } \ |
867 if (__offs > 0) \ |
867 if (__offs > 0) \ |
868 (ret) = __offs; \ |
868 (ret) = __offs; \ |
869 } else { \ |
869 } else { \ |
870 int __offs = 0, __cnt; \ |
870 int __offs = 0, __cnt; \ |
871 int fd = fileno(f); \ |
871 int fd = fileno(f); \ |
872 \ |
872 \ |
873 while (__offs < (cnt)) { \ |
873 while (__offs < (cnt)) { \ |
874 OBJ rA = __INST(readAhead); \ |
874 OBJ rA = __INST(readAhead); \ |
875 if (rA != nil) { \ |
875 if (rA != nil) { \ |
876 DEBUGBUFFER(buf); \ |
876 DEBUGBUFFER(buf); \ |
877 (buf)[__offs] = __intVal(rA); \ |
877 (buf)[__offs] = __intVal(rA); \ |
878 __INST(readAhead) = nil; \ |
878 __INST(readAhead) = nil; \ |
879 __offs++; \ |
879 __offs++; \ |
880 } else { \ |
880 } else { \ |
881 CLEAR_ERRNO; \ |
881 CLEAR_ERRNO; \ |
882 __cnt = read(fd, (buf)+__offs, (cnt)-__offs); \ |
882 __cnt = read(fd, (buf)+__offs, (cnt)-__offs); \ |
883 DEBUGBUFFER(buf); \ |
883 DEBUGBUFFER(buf); \ |
884 if (__cnt <= 0) { \ |
884 if (__cnt <= 0) { \ |
885 if (__cnt < 0 && errno == EINTR) { \ |
885 if (__cnt < 0 && errno == EINTR) { \ |
886 __HANDLE_INTERRUPTS__; \ |
886 __HANDLE_INTERRUPTS__; \ |
887 continue; \ |
887 continue; \ |
888 } \ |
888 } \ |
889 break; \ |
889 break; \ |
890 } \ |
890 } \ |
891 __offs += __cnt; \ |
891 __offs += __cnt; \ |
892 } \ |
892 } \ |
893 } \ |
893 } \ |
894 if (__offs > 0) \ |
894 if (__offs > 0) \ |
895 (ret) = __offs; \ |
895 (ret) = __offs; \ |
896 } |
896 } |
897 |
897 |
898 |
898 |
899 /* |
899 /* |
900 * FNDELAY and O_NDELAY is deprecated, O_NONBLOCK is used in POSIX, XPG, etc... |
900 * FNDELAY and O_NDELAY is deprecated, O_NONBLOCK is used in POSIX, XPG, etc... |
901 */ |
901 */ |
902 |
902 |
903 # if defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(O_NDELAY) || defined(FNDELAY)) |
903 # if defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(O_NDELAY) || defined(FNDELAY)) |
904 # define SETFLAGS(fd, flags) \ |
904 # define SETFLAGS(fd, flags) \ |
905 fcntl(fd, F_SETFL, flags) |
905 fcntl(fd, F_SETFL, flags) |
906 |
906 |
907 # if defined(O_NONBLOCK) |
907 # if defined(O_NONBLOCK) |
908 # define __STX_NONBLOCK_FLAG O_NONBLOCK |
908 # define __STX_NONBLOCK_FLAG O_NONBLOCK |
909 # else |
909 # else |
910 # if defined(O_NDELAY) |
910 # if defined(O_NDELAY) |
913 # define __STX_NONBLOCK_FLAG FNDELAY |
913 # define __STX_NONBLOCK_FLAG FNDELAY |
914 # endif |
914 # endif |
915 # endif |
915 # endif |
916 |
916 |
917 # define SETNONBLOCKING(fd, oldFlags) \ |
917 # define SETNONBLOCKING(fd, oldFlags) \ |
918 { \ |
918 { \ |
919 int flags = fcntl(fd, F_GETFL, 0); \ |
919 int flags = fcntl(fd, F_GETFL, 0); \ |
920 if (flags >= 0) { \ |
920 if (flags >= 0) { \ |
921 fcntl(fd, F_SETFL, flags | __STX_NONBLOCK_FLAG); \ |
921 fcntl(fd, F_SETFL, flags | __STX_NONBLOCK_FLAG); \ |
922 } \ |
922 } \ |
923 oldFlags = flags; \ |
923 oldFlags = flags; \ |
924 } |
924 } |
925 # else |
925 # else |
926 # define SETFLAGS(fd, flags) /* nothing */ |
926 # define SETFLAGS(fd, flags) /* nothing */ |
927 # define SETNONBLOCKING(fd, oldFlags) /* nothing */ |
927 # define SETNONBLOCKING(fd, oldFlags) /* nothing */ |
928 # endif |
928 # endif |
929 |
929 |
930 # define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
930 # define __READAVAILBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
931 { \ |
931 { \ |
932 int __offs = 0, __cnt; \ |
932 int __offs = 0, __cnt; \ |
933 int oldFlags; \ |
933 int oldFlags; \ |
934 \ |
934 \ |
935 (ret) = 0; \ |
935 (ret) = 0; \ |
936 SETNONBLOCKING(fileno(f), oldFlags); \ |
936 SETNONBLOCKING(fileno(f), oldFlags); \ |
937 if (isBuffered) { \ |
937 if (isBuffered) { \ |
938 while (__offs < (cnt)) { \ |
938 while (__offs < (cnt)) { \ |
939 CLEAR_ERRNO; \ |
939 CLEAR_ERRNO; \ |
940 (ret) = getc(f); \ |
940 (ret) = getc(f); \ |
941 if ((ret) < 0) { \ |
941 if ((ret) < 0) { \ |
942 if (ferror(f)) { \ |
942 if (ferror(f)) { \ |
943 if (errno == EINTR) { \ |
943 if (errno == EINTR) { \ |
944 (ret) = 0; \ |
944 (ret) = 0; \ |
945 clearerr(f); \ |
945 clearerr(f); \ |
946 break; \ |
946 break; \ |
947 } \ |
947 } \ |
948 } else { \ |
948 } else { \ |
949 (ret) = 0; \ |
949 (ret) = 0; \ |
950 } \ |
950 } \ |
951 break; \ |
951 break; \ |
952 } \ |
952 } \ |
953 (buf)[__offs++] = (ret); \ |
953 (buf)[__offs++] = (ret); \ |
954 DEBUGBUFFER(buf); \ |
954 DEBUGBUFFER(buf); \ |
955 } \ |
955 } \ |
956 if (__offs > 0) \ |
956 if (__offs > 0) \ |
957 (ret) = __offs; \ |
957 (ret) = __offs; \ |
958 } else { \ |
958 } else { \ |
959 int fd = fileno(f); \ |
959 int fd = fileno(f); \ |
960 \ |
960 \ |
961 while (__offs < (cnt)) { \ |
961 while (__offs < (cnt)) { \ |
962 OBJ rA = __INST(readAhead); \ |
962 OBJ rA = __INST(readAhead); \ |
963 if (rA != nil) { \ |
963 if (rA != nil) { \ |
964 (buf)[__offs] = __intVal(rA); \ |
964 (buf)[__offs] = __intVal(rA); \ |
965 DEBUGBUFFER(buf); \ |
965 DEBUGBUFFER(buf); \ |
966 __INST(readAhead) = nil; \ |
966 __INST(readAhead) = nil; \ |
967 __offs++; \ |
967 __offs++; \ |
968 continue; \ |
968 continue; \ |
969 } \ |
969 } \ |
970 CLEAR_ERRNO; \ |
970 CLEAR_ERRNO; \ |
971 __cnt = read(fd, (buf)+__offs, (cnt)-__offs); \ |
971 __cnt = read(fd, (buf)+__offs, (cnt)-__offs); \ |
972 DEBUGBUFFER(buf); \ |
972 DEBUGBUFFER(buf); \ |
973 if (__cnt > 0) { \ |
973 if (__cnt > 0) { \ |
974 __offs += __cnt; \ |
974 __offs += __cnt; \ |
975 } \ |
975 } \ |
976 break; \ |
976 break; \ |
977 } \ |
977 } \ |
978 if (__offs > 0) \ |
978 if (__offs > 0) \ |
979 (ret) = __offs; \ |
979 (ret) = __offs; \ |
980 } \ |
980 } \ |
981 SETFLAGS(fileno(f), oldFlags); \ |
981 SETFLAGS(fileno(f), oldFlags); \ |
982 } |
982 } |
983 |
983 |
984 # endif /* use STDIO */ |
984 # endif /* use STDIO */ |
992 { \ |
992 { \ |
993 int __ooffs = obj_offs; \ |
993 int __ooffs = obj_offs; \ |
994 int __offs = 0; \ |
994 int __offs = 0; \ |
995 int __cnt; \ |
995 int __cnt; \ |
996 char *buf = (char *)(obj); \ |
996 char *buf = (char *)(obj); \ |
997 \ |
997 \ |
998 (ret) = 0; \ |
998 (ret) = 0; \ |
999 { \ |
999 { \ |
1000 while (__offs < (cnt)) { \ |
1000 while (__offs < (cnt)) { \ |
1001 OBJ rA = __INST(readAhead); \ |
1001 OBJ rA = __INST(readAhead); \ |
1002 if (rA != nil) { \ |
1002 if (rA != nil) { \ |
1003 (buf)[__ooffs+__offs] = __intVal(rA); \ |
1003 (buf)[__ooffs+__offs] = __intVal(rA); \ |
1004 DEBUGBUFFER(buf); \ |
1004 DEBUGBUFFER(buf); \ |
1005 __INST(readAhead) = nil; \ |
1005 __INST(readAhead) = nil; \ |
1006 __offs++; \ |
1006 __offs++; \ |
1007 } else { \ |
1007 } else { \ |
1008 CLEAR_ERRNO; \ |
1008 CLEAR_ERRNO; \ |
1009 __cnt = READ(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \ |
1009 __cnt = READ(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \ |
1010 DEBUGBUFFER(buf); \ |
1010 DEBUGBUFFER(buf); \ |
1011 if (__cnt <= 0) { \ |
1011 if (__cnt <= 0) { \ |
1012 if (__cnt < 0 && errno == EINTR) { \ |
1012 if (__cnt < 0 && errno == EINTR) { \ |
1013 __HANDLE_INTERRUPTS__; \ |
1013 __HANDLE_INTERRUPTS__; \ |
1014 /* refetch */ \ |
1014 /* refetch */ \ |
1015 buf = (char *)(obj); \ |
1015 buf = (char *)(obj); \ |
1016 continue; \ |
1016 continue; \ |
1017 } \ |
1017 } \ |
1018 break; \ |
1018 break; \ |
1019 } \ |
1019 } \ |
1020 __offs += __cnt; \ |
1020 __offs += __cnt; \ |
1021 } \ |
1021 } \ |
1022 } \ |
1022 } \ |
1023 if (__offs > 0) \ |
1023 if (__offs > 0) \ |
1024 (ret) = __offs; \ |
1024 (ret) = __offs; \ |
1025 } \ |
1025 } \ |
1026 } |
1026 } |
1027 |
1027 |
1028 # else /* use STDIO */ |
1028 # else /* use STDIO */ |
1029 |
1029 |
1031 { \ |
1031 { \ |
1032 int __ooffs = obj_offs; \ |
1032 int __ooffs = obj_offs; \ |
1033 int __offs = 0; \ |
1033 int __offs = 0; \ |
1034 int __cnt; \ |
1034 int __cnt; \ |
1035 char *buf = (char *)(obj); \ |
1035 char *buf = (char *)(obj); \ |
1036 \ |
1036 \ |
1037 (ret) = 0; \ |
1037 (ret) = 0; \ |
1038 if (isBuffered) { \ |
1038 if (isBuffered) { \ |
1039 while (__offs < (cnt)) { \ |
1039 while (__offs < (cnt)) { \ |
1040 CLEAR_ERRNO; \ |
1040 CLEAR_ERRNO; \ |
1041 (ret) = getc(f); \ |
1041 (ret) = getc(f); \ |
1042 if ((ret) < 0) { \ |
1042 if ((ret) < 0) { \ |
1043 if (ferror(f)) { \ |
1043 if (ferror(f)) { \ |
1044 if (errno == EINTR) { \ |
1044 if (errno == EINTR) { \ |
1045 __HANDLE_INTERRUPTS__; \ |
1045 __HANDLE_INTERRUPTS__; \ |
1046 clearerr(f); \ |
1046 clearerr(f); \ |
1047 /* refetch */ \ |
1047 /* refetch */ \ |
1048 buf = (char *)(obj); \ |
1048 buf = (char *)(obj); \ |
1049 DEBUGBUFFER(buf); \ |
1049 DEBUGBUFFER(buf); \ |
1050 continue; \ |
1050 continue; \ |
1051 } \ |
1051 } \ |
1052 } else { \ |
1052 } else { \ |
1053 (ret) = 0; \ |
1053 (ret) = 0; \ |
1054 } \ |
1054 } \ |
1055 break; \ |
1055 break; \ |
1056 } \ |
1056 } \ |
1057 (buf)[__ooffs+__offs] = (ret); \ |
1057 (buf)[__ooffs+__offs] = (ret); \ |
1058 DEBUGBUFFER(buf); \ |
1058 DEBUGBUFFER(buf); \ |
1059 __offs++; \ |
1059 __offs++; \ |
1060 } \ |
1060 } \ |
1061 if (__offs > 0) \ |
1061 if (__offs > 0) \ |
1062 (ret) = __offs; \ |
1062 (ret) = __offs; \ |
1063 } else { \ |
1063 } else { \ |
1064 int fd = fileno(f); \ |
1064 int fd = fileno(f); \ |
1065 \ |
1065 \ |
1066 while (__offs < (cnt)) { \ |
1066 while (__offs < (cnt)) { \ |
1067 OBJ rA = __INST(readAhead); \ |
1067 OBJ rA = __INST(readAhead); \ |
1068 if (rA != nil) { \ |
1068 if (rA != nil) { \ |
1069 (buf)[__ooffs+__offs] = __intVal(rA); \ |
1069 (buf)[__ooffs+__offs] = __intVal(rA); \ |
1070 DEBUGBUFFER(buf); \ |
1070 DEBUGBUFFER(buf); \ |
1071 __INST(readAhead) = nil; \ |
1071 __INST(readAhead) = nil; \ |
1072 __offs++; \ |
1072 __offs++; \ |
1073 } else { \ |
1073 } else { \ |
1074 CLEAR_ERRNO; \ |
1074 CLEAR_ERRNO; \ |
1075 __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \ |
1075 __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \ |
1076 DEBUGBUFFER(buf); \ |
1076 DEBUGBUFFER(buf); \ |
1077 if (__cnt <= 0) { \ |
1077 if (__cnt <= 0) { \ |
1078 if (__cnt < 0 && errno == EINTR) { \ |
1078 if (__cnt < 0 && errno == EINTR) { \ |
1079 __HANDLE_INTERRUPTS__; \ |
1079 __HANDLE_INTERRUPTS__; \ |
1080 /* refetch */ \ |
1080 /* refetch */ \ |
1081 buf = (char *)(obj); \ |
1081 buf = (char *)(obj); \ |
1082 continue; \ |
1082 continue; \ |
1083 } \ |
1083 } \ |
1084 break; \ |
1084 break; \ |
1085 } \ |
1085 } \ |
1086 __offs += __cnt; \ |
1086 __offs += __cnt; \ |
1087 } \ |
1087 } \ |
1088 } \ |
1088 } \ |
1089 if (__offs > 0) \ |
1089 if (__offs > 0) \ |
1090 (ret) = __offs; \ |
1090 (ret) = __offs; \ |
1091 } \ |
1091 } \ |
1092 } |
1092 } |
1093 |
1093 |
1094 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
1094 # define __READAVAILBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
1095 { \ |
1095 { \ |
1096 int __ooffs = obj_offs; \ |
1096 int __ooffs = obj_offs; \ |
1097 int __offs = 0; \ |
1097 int __offs = 0; \ |
1098 int __cnt; \ |
1098 int __cnt; \ |
1099 char *buf = (char *)(obj); \ |
1099 char *buf = (char *)(obj); \ |
1100 int oldFlags; \ |
1100 int oldFlags; \ |
1101 \ |
1101 \ |
1102 (ret) = 0; \ |
1102 (ret) = 0; \ |
1103 SETNONBLOCKING(fileno(f), oldFlags); \ |
1103 SETNONBLOCKING(fileno(f), oldFlags); \ |
1104 \ |
1104 \ |
1105 if (isBuffered) { \ |
1105 if (isBuffered) { \ |
1106 while (__offs < (cnt)) { \ |
1106 while (__offs < (cnt)) { \ |
1107 CLEAR_ERRNO; \ |
1107 CLEAR_ERRNO; \ |
1108 (ret) = getc(f); \ |
1108 (ret) = getc(f); \ |
1109 if ((ret) < 0) { \ |
1109 if ((ret) < 0) { \ |
1110 if (ferror(f)) { \ |
1110 if (ferror(f)) { \ |
1111 if (errno == EINTR) { \ |
1111 if (errno == EINTR) { \ |
1112 clearerr(f); \ |
1112 clearerr(f); \ |
1113 /* refetch */ \ |
1113 /* refetch */ \ |
1114 buf = (char *)(obj); \ |
1114 buf = (char *)(obj); \ |
1115 (ret) = 0; \ |
1115 (ret) = 0; \ |
1116 break; \ |
1116 break; \ |
1117 } \ |
1117 } \ |
1118 } else { \ |
1118 } else { \ |
1119 (ret) = 0; \ |
1119 (ret) = 0; \ |
1120 } \ |
1120 } \ |
1121 break; \ |
1121 break; \ |
1122 } \ |
1122 } \ |
1123 (buf)[__ooffs+__offs] = (ret); \ |
1123 (buf)[__ooffs+__offs] = (ret); \ |
1124 DEBUGBUFFER(buf); \ |
1124 DEBUGBUFFER(buf); \ |
1125 __offs++; \ |
1125 __offs++; \ |
1126 } \ |
1126 } \ |
1127 if (__offs > 0) \ |
1127 if (__offs > 0) \ |
1128 (ret) = __offs; \ |
1128 (ret) = __offs; \ |
1129 } else { \ |
1129 } else { \ |
1130 int fd = fileno(f); \ |
1130 int fd = fileno(f); \ |
1131 \ |
1131 \ |
1132 while (__offs < (cnt)) { \ |
1132 while (__offs < (cnt)) { \ |
1133 OBJ rA = __INST(readAhead); \ |
1133 OBJ rA = __INST(readAhead); \ |
1134 if (rA != nil) { \ |
1134 if (rA != nil) { \ |
1135 (buf)[__ooffs+__offs] = __intVal(rA); \ |
1135 (buf)[__ooffs+__offs] = __intVal(rA); \ |
1136 DEBUGBUFFER(buf); \ |
1136 DEBUGBUFFER(buf); \ |
1137 __INST(readAhead) = nil; \ |
1137 __INST(readAhead) = nil; \ |
1138 __offs++; \ |
1138 __offs++; \ |
1139 continue; \ |
1139 continue; \ |
1140 } \ |
1140 } \ |
1141 CLEAR_ERRNO; \ |
1141 CLEAR_ERRNO; \ |
1142 __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \ |
1142 __cnt = read(fd, (buf)+__ooffs+__offs, (cnt)-__offs); \ |
1143 DEBUGBUFFER(buf); \ |
1143 DEBUGBUFFER(buf); \ |
1144 if (__cnt > 0) { \ |
1144 if (__cnt > 0) { \ |
1145 __offs += __cnt; \ |
1145 __offs += __cnt; \ |
1146 } \ |
1146 } \ |
1147 break; \ |
1147 break; \ |
1148 } \ |
1148 } \ |
1149 if (__offs > 0) \ |
1149 if (__offs > 0) \ |
1150 (ret) = __offs; \ |
1150 (ret) = __offs; \ |
1151 } \ |
1151 } \ |
1152 SETFLAGS(fileno(f), oldFlags); \ |
1152 SETFLAGS(fileno(f), oldFlags); \ |
1153 } |
1153 } |
1154 |
1154 |
1155 |
1155 |
1156 # endif /* use STDIO */ |
1156 # endif /* use STDIO */ |
1157 |
1157 |
1158 # ifdef NO_STDIO |
1158 # ifdef NO_STDIO |
1159 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType) \ |
1159 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType) \ |
1160 for (;;) { \ |
1160 for (;;) { \ |
1161 CLEAR_ERRNO; \ |
1161 CLEAR_ERRNO; \ |
1162 (ret) = WRITE(f, buf, 1, handleType); \ |
1162 (ret) = WRITE(f, buf, 1, handleType); \ |
1163 if ((ret) >= 0) break; \ |
1163 if ((ret) >= 0) break; \ |
1164 if (errno != EINTR) { \ |
1164 if (errno != EINTR) { \ |
1165 break; \ |
1165 break; \ |
1166 } \ |
1166 } \ |
1167 __HANDLE_INTERRUPTS__; \ |
1167 __HANDLE_INTERRUPTS__; \ |
1168 } |
1168 } |
1169 # else /* use STDIO */ |
1169 # else /* use STDIO */ |
1170 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType) \ |
1170 # define __WRITEBYTE__(ret, f, buf, isBuffered, handleType) \ |
1171 if (isBuffered) { \ |
1171 if (isBuffered) { \ |
1172 for (;;) { \ |
1172 for (;;) { \ |
1173 CLEAR_ERRNO; \ |
1173 CLEAR_ERRNO; \ |
1174 ret = putc(*(buf), f); \ |
1174 ret = putc(*(buf), f); \ |
1175 if ((ret) >= 0) { \ |
1175 if ((ret) >= 0) { \ |
1176 (ret) = 1; \ |
1176 (ret) = 1; \ |
1177 } else if (ferror(f)) { \ |
1177 } else if (ferror(f)) { \ |
1178 /* SOLARIS/SPARC (2.6) generates spurious errors with errno = 0 */ \ |
1178 /* SOLARIS/SPARC (2.6) generates spurious errors with errno = 0 */ \ |
1179 if (errno == EINTR || errno == 0) { \ |
1179 if (errno == EINTR || errno == 0) { \ |
1180 __HANDLE_INTERRUPTS__; \ |
1180 __HANDLE_INTERRUPTS__; \ |
1181 clearerr(f); \ |
1181 clearerr(f); \ |
1182 continue; \ |
1182 continue; \ |
1183 } \ |
1183 } \ |
1184 } else \ |
1184 } else \ |
1185 (ret) = 0; \ |
1185 (ret) = 0; \ |
1186 break; \ |
1186 break; \ |
1187 } \ |
1187 } \ |
1188 } else { \ |
1188 } else { \ |
1189 for (;;) { \ |
1189 for (;;) { \ |
1190 CLEAR_ERRNO; \ |
1190 CLEAR_ERRNO; \ |
1191 (ret) = write(fileno(f), buf, 1); \ |
1191 (ret) = write(fileno(f), buf, 1); \ |
1192 if ((ret) >= 0) break; \ |
1192 if ((ret) >= 0) break; \ |
1193 if (errno != EINTR) { \ |
1193 if (errno != EINTR) { \ |
1194 break; \ |
1194 break; \ |
1195 } \ |
1195 } \ |
1196 __HANDLE_INTERRUPTS__; \ |
1196 __HANDLE_INTERRUPTS__; \ |
1197 } \ |
1197 } \ |
1198 } |
1198 } |
1199 # endif /* use STDIO */ |
1199 # endif /* use STDIO */ |
1200 |
1200 |
1201 /* |
1201 /* |
1202 * write_bytes from a c-buffer |
1202 * write_bytes from a c-buffer |
1204 */ |
1204 */ |
1205 # ifdef NO_STDIO |
1205 # ifdef NO_STDIO |
1206 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
1206 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
1207 (ret) = 0; \ |
1207 (ret) = 0; \ |
1208 { \ |
1208 { \ |
1209 int __offs = 0; \ |
1209 int __offs = 0; \ |
1210 while (__offs < (cnt)) { \ |
1210 while (__offs < (cnt)) { \ |
1211 CLEAR_ERRNO; \ |
1211 CLEAR_ERRNO; \ |
1212 ret = WRITE(f, (buf)+__offs, (cnt)-__offs, handleType); \ |
1212 ret = WRITE(f, (buf)+__offs, (cnt)-__offs, handleType); \ |
1213 if (ret <= 0) { \ |
1213 if (ret <= 0) { \ |
1214 if (ret < 0 && errno == EINTR) { \ |
1214 if (ret < 0 && errno == EINTR) { \ |
1215 __HANDLE_INTERRUPTS__; \ |
1215 __HANDLE_INTERRUPTS__; \ |
1216 continue; \ |
1216 continue; \ |
1217 } \ |
1217 } \ |
1218 break; \ |
1218 break; \ |
1219 } \ |
1219 } \ |
1220 __offs += (ret); \ |
1220 __offs += (ret); \ |
1221 } \ |
1221 } \ |
1222 if (__offs > 0) \ |
1222 if (__offs > 0) \ |
1223 (ret) = __offs; \ |
1223 (ret) = __offs; \ |
1224 } |
1224 } |
1225 # else /* use STDIO */ |
1225 # else /* use STDIO */ |
1226 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
1226 # define __WRITEBYTES__(ret, f, buf, cnt, isBuffered, handleType) \ |
1227 (ret) = 0; \ |
1227 (ret) = 0; \ |
1228 if (isBuffered) { \ |
1228 if (isBuffered) { \ |
1229 int __offs = 0; \ |
1229 int __offs = 0; \ |
1230 while (__offs < (cnt)) { \ |
1230 while (__offs < (cnt)) { \ |
1231 CLEAR_ERRNO; \ |
1231 CLEAR_ERRNO; \ |
1232 (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\ |
1232 (ret) = fwrite((buf)+__offs, 1, (cnt)-__offs, f);\ |
1233 if ((ret) <= 0) { \ |
1233 if ((ret) <= 0) { \ |
1234 if (ferror(f)) { \ |
1234 if (ferror(f)) { \ |
1235 if (errno == EINTR) { \ |
1235 if (errno == EINTR) { \ |
1236 __HANDLE_INTERRUPTS__; \ |
1236 __HANDLE_INTERRUPTS__; \ |
1237 clearerr(f); \ |
1237 clearerr(f); \ |
1238 continue; \ |
1238 continue; \ |
1239 } \ |
1239 } \ |
1240 } else { \ |
1240 } else { \ |
1241 (ret) = 0; \ |
1241 (ret) = 0; \ |
1242 } \ |
1242 } \ |
1243 break; \ |
1243 break; \ |
1244 } \ |
1244 } \ |
1245 __offs += (ret); \ |
1245 __offs += (ret); \ |
1246 } \ |
1246 } \ |
1247 if (__offs > 0) \ |
1247 if (__offs > 0) \ |
1248 (ret) = __offs; \ |
1248 (ret) = __offs; \ |
1249 } else { \ |
1249 } else { \ |
1250 int __offs = 0; \ |
1250 int __offs = 0; \ |
1251 while (__offs < (cnt)) { \ |
1251 while (__offs < (cnt)) { \ |
1252 CLEAR_ERRNO; \ |
1252 CLEAR_ERRNO; \ |
1253 (ret) = write(fileno(f), (buf)+__offs, (cnt)-__offs);\ |
1253 (ret) = write(fileno(f), (buf)+__offs, (cnt)-__offs);\ |
1254 if ((ret) <= 0) { \ |
1254 if ((ret) <= 0) { \ |
1255 if ((ret) < 0) { \ |
1255 if ((ret) < 0) { \ |
1256 if (errno == EINTR) { \ |
1256 if (errno == EINTR) { \ |
1257 __HANDLE_INTERRUPTS__; \ |
1257 __HANDLE_INTERRUPTS__; \ |
1258 continue; \ |
1258 continue; \ |
1259 } \ |
1259 } \ |
1260 } \ |
1260 } \ |
1261 break; \ |
1261 break; \ |
1262 } \ |
1262 } \ |
1263 __offs += (ret); \ |
1263 __offs += (ret); \ |
1264 } \ |
1264 } \ |
1265 if (__offs > 0) \ |
1265 if (__offs > 0) \ |
1266 (ret) = __offs; \ |
1266 (ret) = __offs; \ |
1267 } |
1267 } |
1268 # endif /* use STDIO */ |
1268 # endif /* use STDIO */ |
1269 |
1269 |
1270 /* |
1270 /* |
1271 * write_bytes from an object |
1271 * write_bytes from an object |
1275 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
1275 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
1276 { \ |
1276 { \ |
1277 int __ooffs = obj_offs; \ |
1277 int __ooffs = obj_offs; \ |
1278 int __offs = 0; \ |
1278 int __offs = 0; \ |
1279 char *buf = (char *)(obj); \ |
1279 char *buf = (char *)(obj); \ |
1280 \ |
1280 \ |
1281 (ret) = 0; \ |
1281 (ret) = 0; \ |
1282 { \ |
1282 { \ |
1283 while (__offs < (cnt)) { \ |
1283 while (__offs < (cnt)) { \ |
1284 CLEAR_ERRNO; \ |
1284 CLEAR_ERRNO; \ |
1285 ret = WRITE(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \ |
1285 ret = WRITE(f, (buf)+__ooffs+__offs, (cnt)-__offs, handleType); \ |
1286 if (ret <= 0) { \ |
1286 if (ret <= 0) { \ |
1287 if (ret < 0 && errno == EINTR) { \ |
1287 if (ret < 0 && errno == EINTR) { \ |
1288 __HANDLE_INTERRUPTS__; \ |
1288 __HANDLE_INTERRUPTS__; \ |
1289 /* refetch */ \ |
1289 /* refetch */ \ |
1290 buf = (char *)(obj); \ |
1290 buf = (char *)(obj); \ |
1291 continue; \ |
1291 continue; \ |
1292 } \ |
1292 } \ |
1293 break; \ |
1293 break; \ |
1294 } \ |
1294 } \ |
1295 __offs += (ret); \ |
1295 __offs += (ret); \ |
1296 } \ |
1296 } \ |
1297 if (__offs > 0) \ |
1297 if (__offs > 0) \ |
1298 (ret) = __offs; \ |
1298 (ret) = __offs; \ |
1299 } \ |
1299 } \ |
1300 } |
1300 } |
1301 # else /* use STDIO */ |
1301 # else /* use STDIO */ |
1302 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
1302 # define __WRITEBYTES_OBJ__(ret, f, obj, obj_offs, cnt, isBuffered, handleType) \ |
1303 { \ |
1303 { \ |
1304 int __ooffs = obj_offs; \ |
1304 int __ooffs = obj_offs; \ |
1305 int __offs = 0; \ |
1305 int __offs = 0; \ |
1306 char *buf = (char *)(obj); \ |
1306 char *buf = (char *)(obj); \ |
1307 \ |
1307 \ |
1308 (ret) = 0; \ |
1308 (ret) = 0; \ |
1309 if (isBuffered) { \ |
1309 if (isBuffered) { \ |
1310 while (__offs < (cnt)) { \ |
1310 while (__offs < (cnt)) { \ |
1311 CLEAR_ERRNO; \ |
1311 CLEAR_ERRNO; \ |
1312 (ret) = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f); \ |
1312 (ret) = fwrite((buf)+__ooffs+__offs, 1, (cnt)-__offs, f); \ |
1313 if ((ret) <= 0) { \ |
1313 if ((ret) <= 0) { \ |
1314 if (ferror(f)) { \ |
1314 if (ferror(f)) { \ |
1315 if (errno == EINTR) { \ |
1315 if (errno == EINTR) { \ |
1316 __HANDLE_INTERRUPTS__; \ |
1316 __HANDLE_INTERRUPTS__; \ |
1317 /* refetch */ \ |
1317 /* refetch */ \ |
1318 buf = (char *)(obj); \ |
1318 buf = (char *)(obj); \ |
1319 clearerr(f); \ |
1319 clearerr(f); \ |
1320 continue; \ |
1320 continue; \ |
1321 } \ |
1321 } \ |
1322 break; \ |
1322 break; \ |
1323 } else { \ |
1323 } else { \ |
1324 (ret) = 0; \ |
1324 (ret) = 0; \ |
1325 } \ |
1325 } \ |
1326 } \ |
1326 } \ |
1327 __offs += (ret); \ |
1327 __offs += (ret); \ |
1328 } \ |
1328 } \ |
1329 } else { \ |
1329 } else { \ |
1330 while (__offs < (cnt)) { \ |
1330 while (__offs < (cnt)) { \ |
1331 CLEAR_ERRNO; \ |
1331 CLEAR_ERRNO; \ |
1332 (ret) = write(fileno(f), (buf)+__ooffs+__offs, (cnt)-__offs); \ |
1332 (ret) = write(fileno(f), (buf)+__ooffs+__offs, (cnt)-__offs); \ |
1333 if ((ret) <= 0) { \ |
1333 if ((ret) <= 0) { \ |
1334 if ((ret) < 0) { \ |
1334 if ((ret) < 0) { \ |
1335 if (errno == EINTR){ \ |
1335 if (errno == EINTR){ \ |
1336 __HANDLE_INTERRUPTS__; \ |
1336 __HANDLE_INTERRUPTS__; \ |
1337 /* refetch */ \ |
1337 /* refetch */ \ |
1338 buf = (char *)(obj); \ |
1338 buf = (char *)(obj); \ |
1339 continue; \ |
1339 continue; \ |
1340 } \ |
1340 } \ |
1341 } \ |
1341 } \ |
1342 break; \ |
1342 break; \ |
1343 } \ |
1343 } \ |
1344 __offs += (ret); \ |
1344 __offs += (ret); \ |
1345 } \ |
1345 } \ |
1346 } \ |
1346 } \ |
1347 if (__offs > 0) \ |
1347 if (__offs > 0) \ |
1348 (ret) = __offs; \ |
1348 (ret) = __offs; \ |
1349 } |
1349 } |
1350 # endif /* use STDIO */ |
1350 # endif /* use STDIO */ |
1351 #endif /* unix */ |
1351 #endif /* unix */ |
1352 %} |
1352 %} |
1353 ! ! |
1353 ! ! |
1355 !ExternalStream class methodsFor:'documentation'! |
1355 !ExternalStream class methodsFor:'documentation'! |
1356 |
1356 |
1357 copyright |
1357 copyright |
1358 " |
1358 " |
1359 COPYRIGHT (c) 1988 by Claus Gittinger |
1359 COPYRIGHT (c) 1988 by Claus Gittinger |
1360 All Rights Reserved |
1360 All Rights Reserved |
1361 |
1361 |
1362 This software is furnished under a license and may be used |
1362 This software is furnished under a license and may be used |
1363 only in accordance with the terms of that license and with the |
1363 only in accordance with the terms of that license and with the |
1364 inclusion of the above copyright notice. This software may not |
1364 inclusion of the above copyright notice. This software may not |
1365 be provided or otherwise made available to, or used by, any |
1365 be provided or otherwise made available to, or used by, any |
1405 if the contents changed in the meantime. |
1405 if the contents changed in the meantime. |
1406 Therefore, it is a good idea to reopen files and check for these things at restart time. |
1406 Therefore, it is a good idea to reopen files and check for these things at restart time. |
1407 |
1407 |
1408 [Instance variables:] |
1408 [Instance variables:] |
1409 |
1409 |
1410 handleType <Symbol> desribes what handle is: |
1410 handleType <Symbol> desribes what handle is: |
1411 win32: #fileHandle, #socketHandle, |
1411 win32: #fileHandle, #socketHandle, |
1412 #filePointer, #socketFilePointer, #pipeFilePointer |
1412 #filePointer, #socketFilePointer, #pipeFilePointer |
1413 unix: #filePointer, #socketFilePointer, #pipeFilePointer |
1413 unix: #filePointer, #socketFilePointer, #pipeFilePointer |
1414 needed for win32, which uses different APIs for the different handles (sigh) |
1414 needed for win32, which uses different APIs for the different handles (sigh) |
1415 handle <Integer> used to be always a filePointer somehow mapped to an integer (FILE* - not the fd); |
1415 handle <Integer> used to be always a filePointer somehow mapped to an integer (FILE* - not the fd); |
1416 now, either a filePointer or a handle (win32) |
1416 now, either a filePointer or a handle (win32) |
1417 mode <Symbol> #readwrite, #readonly or #writeonly |
1417 mode <Symbol> #readwrite, #readonly or #writeonly |
1418 buffered <Boolean> true, if buffered (i.e. collects characters - does |
1418 buffered <Boolean> true, if buffered (i.e. collects characters - does |
1419 not output immediately) |
1419 not output immediately) |
1420 binary <Boolean> true if in binary mode (reads bytes instead of chars) |
1420 binary <Boolean> true if in binary mode (reads bytes instead of chars) |
1421 eolMode <Symbol> one of nil, #nl, #cr or #crlf. |
1421 eolMode <Symbol> one of nil, #nl, #cr or #crlf. |
1422 determines how lines should be terminated. |
1422 determines how lines should be terminated. |
1423 nil -> newLine (as in Unix); |
1423 nil -> newLine (as in Unix); |
1424 #crlf -> with cr-lf (as in MSDOS) |
1424 #crlf -> with cr-lf (as in MSDOS) |
1425 #cr -> with cr (as in VMS) |
1425 #cr -> with cr (as in VMS) |
1426 hitEOF <Boolean> true, if EOF was reached |
1426 hitEOF <Boolean> true, if EOF was reached |
1427 |
1427 |
1428 lastErrorNumber <Integer> the value of errno (only valid right after the error - |
1428 lastErrorNumber <Integer> the value of errno (only valid right after the error - |
1429 updated with next i/o operation) |
1429 updated with next i/o operation) |
1430 |
1430 |
1431 [Class variables:] |
1431 [Class variables:] |
1432 Lobby <Registry> keeps track of used ext-streams (to free up FILE*'s) |
1432 Lobby <Registry> keeps track of used ext-streams (to free up FILE*'s) |
1433 |
1433 |
1434 StreamErrorSignal <Signal> parent of all stream errors (see Stream class) |
1434 StreamErrorSignal <Signal> parent of all stream errors (see Stream class) |
1435 InvalidReadSignal <Signal> raised on read from writeonly stream |
1435 InvalidReadSignal <Signal> raised on read from writeonly stream |
1436 InvalidWriteSignal <Signal> raised on write to readonly stream |
1436 InvalidWriteSignal <Signal> raised on write to readonly stream |
1437 InvalidModeSignal <Signal> raised on text I/O with binary-stream |
1437 InvalidModeSignal <Signal> raised on text I/O with binary-stream |
1438 or binary I/O with text-stream |
1438 or binary I/O with text-stream |
1439 OpenErrorSignal <Signal> raised if open fails |
1439 OpenErrorSignal <Signal> raised if open fails |
1440 StreamNotOpenSignal <Signal> raised on I/O with non-open stream |
1440 StreamNotOpenSignal <Signal> raised on I/O with non-open stream |
1441 |
1441 |
1442 Additional notes: |
1442 Additional notes: |
1443 This class is implemented using the underlying stdio-c library package, which |
1443 This class is implemented using the underlying stdio-c library package, which |
1444 has both advantages and disadvantages: since it is portable (posix defined), porting |
1444 has both advantages and disadvantages: since it is portable (posix defined), porting |
1445 ST/X to non-Unix machines is simplified. The disadvantage is that the stdio library |
1445 ST/X to non-Unix machines is simplified. The disadvantage is that the stdio library |
1469 fseek whenever we are about to read after write and vice versa. |
1469 fseek whenever we are about to read after write and vice versa. |
1470 Two macros (__READING__ and __WRITING__) have been defined to be used before every |
1470 Two macros (__READING__ and __WRITING__) have been defined to be used before every |
1471 fread/fgetc and fwrite/putc respectively. |
1471 fread/fgetc and fwrite/putc respectively. |
1472 |
1472 |
1473 [author:] |
1473 [author:] |
1474 Claus Gittinger |
1474 Claus Gittinger |
1475 Stefan Vogel (many, many fixes ...) |
1475 Stefan Vogel (many, many fixes ...) |
1476 |
1476 |
1477 [see also:] |
1477 [see also:] |
1478 FileStream Socket PipeStream |
1478 FileStream Socket PipeStream |
1479 Filename OperatingSystem |
1479 Filename OperatingSystem |
1480 " |
1480 " |
1481 ! |
1481 ! |
1482 |
1482 |
1483 examples |
1483 examples |
1484 " |
1484 " |
1485 open a file, read the contents and display it in a textView: |
1485 open a file, read the contents and display it in a textView: |
1486 [exBegin] |
1486 [exBegin] |
1487 |topView scrollPane textView fileStream text| |
1487 |topView scrollPane textView fileStream text| |
1488 |
1488 |
1489 topView := StandardSystemView new. |
1489 topView := StandardSystemView new. |
1490 topView label:'contents of Makefile'. |
1490 topView label:'contents of Makefile'. |
1491 |
1491 |
1492 scrollPane := HVScrollableView in:topView. |
1492 scrollPane := HVScrollableView in:topView. |
1493 scrollPane origin:0.0@0.0 corner:1.0@1.0. |
1493 scrollPane origin:0.0@0.0 corner:1.0@1.0. |
1494 |
1494 |
1495 textView := EditTextView new. |
1495 textView := EditTextView new. |
1496 scrollPane scrolledView:textView. |
1496 scrollPane scrolledView:textView. |
1497 |
1497 |
1498 fileStream := 'Makefile' asFilename readStream. |
1498 fileStream := 'Makefile' asFilename readStream. |
1499 text := fileStream upToEnd. |
1499 text := fileStream upToEnd. |
1500 fileStream close. |
1500 fileStream close. |
1501 |
1501 |
1502 textView contents:text. |
1502 textView contents:text. |
1503 |
1503 |
1504 topView open. |
1504 topView open. |
1505 [exEnd] |
1505 [exEnd] |
1506 |
1506 |
1507 |
1507 |
1508 Notice, all of the above can also be done (simply) as: |
1508 Notice, all of the above can also be done (simply) as: |
1509 [exBegin] |
1509 [exBegin] |
1510 EditTextView openOn:'Makefile' |
1510 EditTextView openOn:'Makefile' |
1511 [exEnd] |
1511 [exEnd] |
1512 " |
1512 " |
1513 ! ! |
1513 ! ! |
1514 |
1514 |
1515 !ExternalStream class methodsFor:'initialization'! |
1515 !ExternalStream class methodsFor:'initialization'! |
1516 |
1516 |
1517 closeFiles |
1517 closeFiles |
1518 "close all files. |
1518 "close all files. |
1519 To be called on exit of Smalltalk." |
1519 To be called on exit of Smalltalk." |
1520 |
1520 |
1521 Lobby do:[:eachFileStream | |
1521 Lobby do:[:eachFileStream | |
1522 (eachFileStream ~~ Stdin |
1522 (eachFileStream ~~ Stdin |
1523 and:[eachFileStream ~~ Stdout |
1523 and:[eachFileStream ~~ Stdout |
1524 and:[eachFileStream ~~ Stderr]]) ifTrue:[ |
1524 and:[eachFileStream ~~ Stderr]]) ifTrue:[ |
1525 eachFileStream close |
1525 eachFileStream close |
1526 ]. |
1526 ]. |
1527 ]. |
1527 ]. |
1528 |
1528 |
1529 "Modified: / 25-04-2018 / 15:23:41 / stefan" |
1529 "Modified: / 25-04-2018 / 15:23:41 / stefan" |
1530 ! |
1530 ! |
1531 |
1531 |
1532 initDefaultEOLMode |
1532 initDefaultEOLMode |
1533 OperatingSystem isUNIXlike ifTrue:[ |
1533 OperatingSystem isUNIXlike ifTrue:[ |
1534 "/ unix EOL conventions |
1534 "/ unix EOL conventions |
1535 DefaultEOLMode := #nl |
1535 DefaultEOLMode := #nl |
1536 ] ifFalse:[ |
1536 ] ifFalse:[ |
1537 OperatingSystem isVMSlike ifTrue:[ |
1537 OperatingSystem isVMSlike ifTrue:[ |
1538 "/ vms EOL conventions |
1538 "/ vms EOL conventions |
1539 DefaultEOLMode := #cr |
1539 DefaultEOLMode := #cr |
1540 ] ifFalse:[ |
1540 ] ifFalse:[ |
1541 "/ msdos EOL conventions |
1541 "/ msdos EOL conventions |
1542 "/ msdos uses #crlf. |
1542 "/ msdos uses #crlf. |
1543 "/ the following breaks all programs, which do not explicitly |
1543 "/ the following breaks all programs, which do not explicitly |
1544 "/ change th eolMode when writing/reading binary files (zip reader) |
1544 "/ change th eolMode when writing/reading binary files (zip reader) |
1545 "/ MUST change all classes before doing the following. |
1545 "/ MUST change all classes before doing the following. |
1546 "/ Anyway: for backward compatibility (swisscom), it is left in this |
1546 "/ Anyway: for backward compatibility (swisscom), it is left in this |
1547 "/ mode (for a while, I hope). |
1547 "/ mode (for a while, I hope). |
1548 DefaultEOLMode := #crlf. |
1548 DefaultEOLMode := #crlf. |
1549 |
1549 |
1550 "/ DefaultEOLMode := #nl |
1550 "/ DefaultEOLMode := #nl |
1551 ] |
1551 ] |
1552 ] |
1552 ] |
1553 ! |
1553 ! |
1554 |
1554 |
1555 initModeStrings |
1555 initModeStrings |
1556 "initialize modeStrings which are passed down to the underlying |
1556 "initialize modeStrings which are passed down to the underlying |
1557 fopen/fdopen functions." |
1557 fopen/fdopen functions." |
1558 |
1558 |
1559 OperatingSystem isMSDOSlike ifTrue:[ |
1559 OperatingSystem isMSDOSlike ifTrue:[ |
1560 ReadMode := 'rb'. |
1560 ReadMode := 'rb'. |
1561 ReadWriteMode := 'rb+'. |
1561 ReadWriteMode := 'rb+'. |
1562 WriteMode := 'wb'. |
1562 WriteMode := 'wb'. |
1563 AppendMode := 'ab+'. |
1563 AppendMode := 'ab+'. |
1564 CreateReadWriteMode := 'wb+'. |
1564 CreateReadWriteMode := 'wb+'. |
1565 ] ifFalse:[ |
1565 ] ifFalse:[ |
1566 ReadMode := 'r'. |
1566 ReadMode := 'r'. |
1567 ReadWriteMode := 'r+'. |
1567 ReadWriteMode := 'r+'. |
1568 WriteMode := 'w'. |
1568 WriteMode := 'w'. |
1569 AppendMode := 'a+'. |
1569 AppendMode := 'a+'. |
1570 CreateReadWriteMode := 'w+'. |
1570 CreateReadWriteMode := 'w+'. |
1571 ] |
1571 ] |
1572 ! |
1572 ! |
1573 |
1573 |
1574 initialize |
1574 initialize |
1575 OpenErrorSignal isNil ifTrue:[ |
1575 OpenErrorSignal isNil ifTrue:[ |
1576 OpenErrorSignal := OpenError. |
1576 OpenErrorSignal := OpenError. |
1577 OpenErrorSignal notifierString:'open error'. |
1577 OpenErrorSignal notifierString:'open error'. |
1578 |
1578 |
1579 InvalidReadSignal := InvalidReadError. |
1579 InvalidReadSignal := InvalidReadError. |
1580 InvalidReadSignal notifierString:'stream does not support reading'. |
1580 InvalidReadSignal notifierString:'stream does not support reading'. |
1581 |
1581 |
1582 InvalidWriteSignal := InvalidWriteError. |
1582 InvalidWriteSignal := InvalidWriteError. |
1583 InvalidWriteSignal notifierString:'stream does not support writing'. |
1583 InvalidWriteSignal notifierString:'stream does not support writing'. |
1584 |
1584 |
1585 InvalidModeSignal := InvalidModeError. |
1585 InvalidModeSignal := InvalidModeError. |
1586 InvalidModeSignal notifierString:'binary/text mode mismatch'. |
1586 InvalidModeSignal notifierString:'binary/text mode mismatch'. |
1587 |
1587 |
1588 InvalidOperationSignal := InvalidOperationError. |
1588 InvalidOperationSignal := InvalidOperationError. |
1589 InvalidOperationSignal notifierString:'unsupported file operation'. |
1589 InvalidOperationSignal notifierString:'unsupported file operation'. |
1590 |
1590 |
1591 StreamNotOpenSignal := StreamNotOpenError. |
1591 StreamNotOpenSignal := StreamNotOpenError. |
1592 StreamNotOpenSignal notifierString:'stream is not open'. |
1592 StreamNotOpenSignal notifierString:'stream is not open'. |
1593 |
1593 |
1594 StreamIOErrorSignal := StreamIOError. |
1594 StreamIOErrorSignal := StreamIOError. |
1595 StreamIOErrorSignal notifierString:'I/O error'. |
1595 StreamIOErrorSignal notifierString:'I/O error'. |
1596 |
1596 |
1597 "/ self patchByteOrderOptimizedMethods |
1597 "/ self patchByteOrderOptimizedMethods |
1598 ]. |
1598 ]. |
1599 |
1599 |
1600 Lobby isNil ifTrue:[ |
1600 Lobby isNil ifTrue:[ |
1601 Lobby := Registry new. |
1601 Lobby := Registry new. |
1602 |
1602 |
1603 "want to get informed when returning from snapshot" |
1603 "want to get informed when returning from snapshot" |
1604 ObjectMemory addDependent:self |
1604 ObjectMemory addDependent:self |
1605 ]. |
1605 ]. |
1606 DefaultEOLMode isNil ifTrue:[ |
1606 DefaultEOLMode isNil ifTrue:[ |
1607 self initDefaultEOLMode. |
1607 self initDefaultEOLMode. |
1608 ]. |
1608 ]. |
1609 ReadMode isNil ifTrue:[ |
1609 ReadMode isNil ifTrue:[ |
1610 self initModeStrings. |
1610 self initModeStrings. |
1611 ]. |
1611 ]. |
1612 |
1612 |
1613 "limit the amount of newspace to be used for non-tenurable executors to 5%" |
1613 "limit the amount of newspace to be used for non-tenurable executors to 5%" |
1614 "/ MaxNonTenurableExecutors := ObjectMemory newSpaceSize // (Socket sizeOfInst:0) // 20. |
1614 "/ MaxNonTenurableExecutors := ObjectMemory newSpaceSize // (Socket sizeOfInst:0) // 20. |
1615 "/ cg: changed because Socket is not in libbasic. Thus, standalone (libbasic only) |
1615 "/ cg: changed because Socket is not in libbasic. Thus, standalone (libbasic only) |
1620 ! |
1620 ! |
1621 |
1621 |
1622 patchByteOrderOptimizedMethods |
1622 patchByteOrderOptimizedMethods |
1623 "EXPERIMENTAL (not yet done by default): |
1623 "EXPERIMENTAL (not yet done by default): |
1624 change the underlying implementation of |
1624 change the underlying implementation of |
1625 nextPutInt16MSB / nextPutInt16LSB |
1625 nextPutInt16MSB / nextPutInt16LSB |
1626 nextPutInt32MSB / nextPutInt32LSB |
1626 nextPutInt32MSB / nextPutInt32LSB |
1627 to the corresponding NATIVE methods." |
1627 to the corresponding NATIVE methods." |
1628 |
1628 |
1629 |native16 native32| |
1629 |native16 native32| |
1630 |
1630 |
1631 native16 := self compiledMethodAt:#nextPutInt16NATIVE:. |
1631 native16 := self compiledMethodAt:#nextPutInt16NATIVE:. |
1632 native32 := self compiledMethodAt:#nextPutInt32NATIVE:. |
1632 native32 := self compiledMethodAt:#nextPutInt32NATIVE:. |
1633 |
1633 |
1634 UninterpretedBytes isBigEndian ifTrue:[ |
1634 UninterpretedBytes isBigEndian ifTrue:[ |
1635 (self compiledMethodAt:#nextPutInt16MSB:) code:(native16 code). |
1635 (self compiledMethodAt:#nextPutInt16MSB:) code:(native16 code). |
1636 (self compiledMethodAt:#nextPutInt32MSB:) code:(native32 code). |
1636 (self compiledMethodAt:#nextPutInt32MSB:) code:(native32 code). |
1637 ] ifFalse:[ |
1637 ] ifFalse:[ |
1638 (self compiledMethodAt:#nextPutInt16LSB:) code:(native16 code). |
1638 (self compiledMethodAt:#nextPutInt16LSB:) code:(native16 code). |
1639 (self compiledMethodAt:#nextPutInt32LSB:) code:(native32 code). |
1639 (self compiledMethodAt:#nextPutInt32LSB:) code:(native32 code). |
1640 ]. |
1640 ]. |
1641 ! |
1641 ! |
1642 |
1642 |
1643 reOpenFiles |
1643 reOpenFiles |
1644 "reopen all files (if possible) after a snapShot load. |
1644 "reopen all files (if possible) after a snapShot load. |
1645 This is invoked via the #earlyRestart change notification." |
1645 This is invoked via the #earlyRestart change notification." |
1646 |
1646 |
1647 Lobby do:[:eachFileStream | |
1647 Lobby do:[:eachFileStream | |
1648 eachFileStream reOpen |
1648 eachFileStream reOpen |
1649 ]. |
1649 ]. |
1650 ! |
1650 ! |
1651 |
1651 |
1652 update:something with:aParameter from:changedObject |
1652 update:something with:aParameter from:changedObject |
1653 "have to reopen files when returning from snapshot" |
1653 "have to reopen files when returning from snapshot" |
1654 |
1654 |
1655 something == #earlyRestart ifTrue:[ |
1655 something == #earlyRestart ifTrue:[ |
1656 self reOpenFiles. |
1656 self reOpenFiles. |
1657 self initDefaultEOLMode |
1657 self initDefaultEOLMode |
1658 ] |
1658 ] |
1659 |
1659 |
1660 "Created: 15.6.1996 / 15:19:59 / cg" |
1660 "Created: 15.6.1996 / 15:19:59 / cg" |
1661 ! ! |
1661 ! ! |
1662 |
1662 |
1690 The modeSymbol-argument is #readonly, #readwrite, .... |
1690 The modeSymbol-argument is #readonly, #readwrite, .... |
1691 This may be used to wrap fd's as returned by user |
1691 This may be used to wrap fd's as returned by user |
1692 primitive code, or to wrap pipe-fds into externalStreams." |
1692 primitive code, or to wrap pipe-fds into externalStreams." |
1693 |
1693 |
1694 ^ self new |
1694 ^ self new |
1695 buffered:buffered; |
1695 buffered:buffered; |
1696 connectTo:aFileDescriptor withMode:modeSymbol handleType:handleTypeSymbol. |
1696 connectTo:aFileDescriptor withMode:modeSymbol handleType:handleTypeSymbol. |
1697 |
1697 |
1698 " |
1698 " |
1699 the example below will probably fail (15 is a random FD): |
1699 the example below will probably fail (15 is a random FD): |
1700 |
1700 |
1701 |s| |
1701 |s| |
1760 rs := ExternalStream forReadingFromFileDescriptor:readFd. |
1760 rs := ExternalStream forReadingFromFileDescriptor:readFd. |
1761 ws := ExternalStream forWritingToFileDescriptor:writeFd. |
1761 ws := ExternalStream forWritingToFileDescriptor:writeFd. |
1762 |
1762 |
1763 'read ...'. |
1763 'read ...'. |
1764 [ |
1764 [ |
1765 1 to:10 do:[:i | |
1765 1 to:10 do:[:i | |
1766 Transcript showCR:rs nextLine |
1766 Transcript showCR:rs nextLine |
1767 ]. |
1767 ]. |
1768 rs close. |
1768 rs close. |
1769 ] forkAt:7. |
1769 ] forkAt:7. |
1770 |
1770 |
1771 'write ...'. |
1771 'write ...'. |
1772 [ |
1772 [ |
1773 1 to:10 do:[:i | |
1773 1 to:10 do:[:i | |
1774 ws nextPutAll:'hello world '; nextPutAll:i printString; cr |
1774 ws nextPutAll:'hello world '; nextPutAll:i printString; cr |
1775 ]. |
1775 ]. |
1776 ws close. |
1776 ws close. |
1777 ] fork. |
1777 ] fork. |
1778 |
1778 |
1779 " |
1779 " |
1780 |
1780 |
1781 "Created: 29.2.1996 / 18:14:24 / cg" |
1781 "Created: 29.2.1996 / 18:14:24 / cg" |
1874 "answer a collection of open Streams having this class" |
1874 "answer a collection of open Streams having this class" |
1875 |
1875 |
1876 |openStreams| |
1876 |openStreams| |
1877 |
1877 |
1878 openStreams := OrderedCollection new. |
1878 openStreams := OrderedCollection new. |
1879 Lobby keysDo:[:eachStream| |
1879 Lobby keysDo:[:eachStream| |
1880 (eachStream isKindOf:self) ifTrue:[ |
1880 (eachStream isKindOf:self) ifTrue:[ |
1881 openStreams add:eachStream |
1881 openStreams add:eachStream |
1882 ] |
1882 ] |
1883 ]. |
1883 ]. |
1884 |
1884 |
1885 ^ openStreams |
1885 ^ openStreams |
1886 |
1886 |
1887 " |
1887 " |
1888 self openStreams |
1888 self openStreams |
1889 Socket openStreams |
1889 Socket openStreams |
1890 NonPositionableExternalStream openStreams |
1890 NonPositionableExternalStream openStreams |
1891 " |
1891 " |
1892 |
1892 |
1893 "Created: / 24-04-2018 / 09:23:33 / stefan" |
1893 "Created: / 24-04-2018 / 09:23:33 / stefan" |
1894 ! ! |
1894 ! ! |
1895 |
1895 |
1907 When nil, a somewhat conservative compromise is used." |
1907 When nil, a somewhat conservative compromise is used." |
1908 |
1908 |
1909 DefaultCopyBufferSize notNil ifTrue:[^ DefaultCopyBufferSize]. |
1909 DefaultCopyBufferSize notNil ifTrue:[^ DefaultCopyBufferSize]. |
1910 |
1910 |
1911 OperatingSystem isMSDOSlike ifTrue:[ |
1911 OperatingSystem isMSDOSlike ifTrue:[ |
1912 OperatingSystem isWin7Like ifTrue:[ |
1912 OperatingSystem isWin7Like ifTrue:[ |
1913 ^ 64*1024 |
1913 ^ 64*1024 |
1914 ] ifFalse:[ |
1914 ] ifFalse:[ |
1915 "/ mhmh - NT hangs, when copying bigger blocks to a network drive - why ? |
1915 "/ mhmh - NT hangs, when copying bigger blocks to a network drive - why ? |
1916 ^ 1 * 1024. |
1916 ^ 1 * 1024. |
1917 ]. |
1917 ]. |
1918 ]. |
1918 ]. |
1919 ^ 32 * 1024. |
1919 ^ 32 * 1024. |
1920 ! |
1920 ! |
1921 |
1921 |
1922 defaultCopyBufferSize:anInteger |
1922 defaultCopyBufferSize:anInteger |
1965 reportOn:anErrorSymbolOrNumber |
1965 reportOn:anErrorSymbolOrNumber |
1966 "an error occurred. |
1966 "an error occurred. |
1967 Report it via an Exception" |
1967 Report it via an Exception" |
1968 |
1968 |
1969 anErrorSymbolOrNumber isInteger ifTrue:[ |
1969 anErrorSymbolOrNumber isInteger ifTrue:[ |
1970 StreamError |
1970 StreamError |
1971 raiseRequestWith:anErrorSymbolOrNumber |
1971 raiseRequestWith:anErrorSymbolOrNumber |
1972 errorString:(' - os error:' , (OperatingSystem errorTextForNumber:anErrorSymbolOrNumber)) |
1972 errorString:(' - os error:' , (OperatingSystem errorTextForNumber:anErrorSymbolOrNumber)) |
1973 ]. |
1973 ]. |
1974 (self respondsTo:anErrorSymbolOrNumber) ifTrue:[ |
1974 (self respondsTo:anErrorSymbolOrNumber) ifTrue:[ |
1975 self perform:anErrorSymbolOrNumber |
1975 self perform:anErrorSymbolOrNumber |
1976 ] ifFalse:[ |
1976 ] ifFalse:[ |
1977 StreamError |
1977 StreamError |
1978 raiseRequestWith:anErrorSymbolOrNumber |
1978 raiseRequestWith:anErrorSymbolOrNumber |
1979 errorString:(' - ' , anErrorSymbolOrNumber printString) |
1979 errorString:(' - ' , anErrorSymbolOrNumber printString) |
1980 ]. |
1980 ]. |
1981 ^ false |
1981 ^ false |
1982 ! ! |
1982 ! ! |
1983 |
1983 |
1984 !ExternalStream class methodsFor:'finalization'! |
1984 !ExternalStream class methodsFor:'finalization'! |
2097 is returned." |
2097 is returned." |
2098 |
2098 |
2099 |text| |
2099 |text| |
2100 |
2100 |
2101 binary ifTrue:[ |
2101 binary ifTrue:[ |
2102 ^ self upToEnd. |
2102 ^ self upToEnd. |
2103 ]. |
2103 ]. |
2104 |
2104 |
2105 "/ text mode |
2105 "/ text mode |
2106 text := StringCollection new. |
2106 text := StringCollection new. |
2107 [self atEnd] whileFalse:[ |
2107 [self atEnd] whileFalse:[ |
2108 |line| |
2108 |line| |
2109 |
2109 |
2110 line := self nextLine. |
2110 line := self nextLine. |
2111 line isNil ifTrue:[ |
2111 line isNil ifTrue:[ |
2112 ^ text |
2112 ^ text |
2113 ]. |
2113 ]. |
2114 text add:line |
2114 text add:line |
2115 ]. |
2115 ]. |
2116 ^ text |
2116 ^ text |
2117 ! |
2117 ! |
2118 |
2118 |
2119 contentsAsString |
2119 contentsAsString |
2120 "to compensate for the bad naming, use this to make things explicit. |
2120 "to compensate for the bad naming, use this to make things explicit. |
2121 See also #contents, which returns the lines as stringCollection for textFiles." |
2121 See also #contents, which returns the lines as stringCollection for textFiles." |
2122 |
2122 |
2123 binary ifTrue:[ |
2123 binary ifTrue:[ |
2124 ^ [ |
2124 ^ [ |
2125 binary := false. |
2125 binary := false. |
2126 self contentsOfEntireFile. |
2126 self contentsOfEntireFile. |
2127 ] ensure:[ |
2127 ] ensure:[ |
2128 binary := true. |
2128 binary := true. |
2129 ]. |
2129 ]. |
2130 ]. |
2130 ]. |
2131 |
2131 |
2132 ^ self contentsOfEntireFile. |
2132 ^ self contentsOfEntireFile. |
2133 |
2133 |
2134 "Modified: / 09-05-2018 / 19:37:36 / stefan" |
2134 "Modified: / 09-05-2018 / 19:37:36 / stefan" |
2147 contentsSpecies |
2147 contentsSpecies |
2148 "return the kind of object to be returned by sub-collection builders |
2148 "return the kind of object to be returned by sub-collection builders |
2149 (such as upTo)" |
2149 (such as upTo)" |
2150 |
2150 |
2151 binary ifTrue:[ |
2151 binary ifTrue:[ |
2152 ^ ByteArray |
2152 ^ ByteArray |
2153 ]. |
2153 ]. |
2154 ^ String |
2154 ^ String |
2155 ! |
2155 ! |
2156 |
2156 |
2157 eolMode |
2157 eolMode |
2158 "return how end-of-line (EOL) is to be marked. |
2158 "return how end-of-line (EOL) is to be marked. |
2159 Returns one one of: |
2159 Returns one one of: |
2160 #crlf -> add a CR-NL, as in MSDOS |
2160 #crlf -> add a CR-NL, as in MSDOS |
2161 #cr -> add a CR, as in VMS |
2161 #cr -> add a CR, as in VMS |
2162 #nl -> add a NL, as in Unix |
2162 #nl -> add a NL, as in Unix |
2163 #eot -> add an EOT (= 0x04, as used in some modems/protocols) |
2163 #eot -> add an EOT (= 0x04, as used in some modems/protocols) |
2164 #etx -> add an ETX (= 0x03, as used in some modems/protocols) |
2164 #etx -> add an ETX (= 0x03, as used in some modems/protocols) |
2165 #nl -> add a NL, as in Unix |
2165 #nl -> add a NL, as in Unix |
2166 nil -> transparent |
2166 nil -> transparent |
2167 " |
2167 " |
2168 |
2168 |
2169 ^ eolMode |
2169 ^ eolMode |
2170 |
2170 |
2171 "Modified (comment): / 06-12-2016 / 14:26:24 / cg" |
2171 "Modified (comment): / 06-12-2016 / 14:26:24 / cg" |
2172 ! |
2172 ! |
2173 |
2173 |
2174 eolMode:aSymbolOrNil |
2174 eolMode:aSymbolOrNil |
2175 "specify how end-of-line (EOL) is to be marked. |
2175 "specify how end-of-line (EOL) is to be marked. |
2176 The argument may be one of: |
2176 The argument may be one of: |
2177 #crlf -> add a CR-NL, as in MSDOS |
2177 #crlf -> add a CR-NL, as in MSDOS |
2178 #cr -> add a CR, as in VMS |
2178 #cr -> add a CR, as in VMS |
2179 #nl -> add a NL, as in Unix |
2179 #nl -> add a NL, as in Unix |
2180 #eot -> add an EOT (= 0x04, as used in some modems/protocols) |
2180 #eot -> add an EOT (= 0x04, as used in some modems/protocols) |
2181 #etx -> add an ETX (= 0x03, as used in some modems/protocols) |
2181 #etx -> add an ETX (= 0x03, as used in some modems/protocols) |
2182 anyOther -> like #nl |
2182 anyOther -> like #nl |
2183 " |
2183 " |
2184 |
2184 |
2185 aSymbolOrNil == #crnl ifTrue:[ |
2185 aSymbolOrNil == #crnl ifTrue:[ |
2186 eolMode := #crlf |
2186 eolMode := #crlf |
2187 ] ifFalse:[ |
2187 ] ifFalse:[ |
2188 aSymbolOrNil == #lf ifTrue:[ |
2188 aSymbolOrNil == #lf ifTrue:[ |
2189 eolMode := #nl |
2189 eolMode := #nl |
2190 ] ifFalse:[ |
2190 ] ifFalse:[ |
2191 eolMode := aSymbolOrNil |
2191 eolMode := aSymbolOrNil |
2192 ] |
2192 ] |
2193 ]. |
2193 ]. |
2194 |
2194 |
2195 "Modified (comment): / 06-12-2016 / 14:26:37 / cg" |
2195 "Modified (comment): / 06-12-2016 / 14:26:37 / cg" |
2196 ! |
2196 ! |
2197 |
2197 |
2205 %{ |
2205 %{ |
2206 OBJ _handle = __INST(handle); |
2206 OBJ _handle = __INST(handle); |
2207 |
2207 |
2208 fileClosed = false; |
2208 fileClosed = false; |
2209 if (_handle != nil) { |
2209 if (_handle != nil) { |
2210 if ((__INST(handleType) == @symbol(fileHandle)) |
2210 if ((__INST(handleType) == @symbol(fileHandle)) |
2211 || (__INST(handleType) == @symbol(socketHandle))) { |
2211 || (__INST(handleType) == @symbol(socketHandle))) { |
2212 RETURN (_handle); |
2212 RETURN (_handle); |
2213 } |
2213 } |
2214 |
2214 |
2215 if ((__INST(handleType) == nil) |
2215 if ((__INST(handleType) == nil) |
2216 || (__INST(handleType) == @symbol(filePointer)) |
2216 || (__INST(handleType) == @symbol(filePointer)) |
2217 || (__INST(handleType) == @symbol(socketFilePointer)) |
2217 || (__INST(handleType) == @symbol(socketFilePointer)) |
2218 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2218 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2219 FILE *file = __FILEVal(_handle); |
2219 FILE *file = __FILEVal(_handle); |
2220 if (file != NULL) { |
2220 if (file != NULL) { |
2221 int fileNo = fileno(file); |
2221 int fileNo = fileno(file); |
2222 |
2222 |
2223 if (fileNo >= 0) { |
2223 if (fileNo >= 0) { |
2224 RETURN ( __MKINT(fileNo)); |
2224 RETURN ( __MKINT(fileNo)); |
2225 } |
2225 } |
2226 fileClosed = true; |
2226 fileClosed = true; |
2227 } |
2227 } |
2228 } |
2228 } |
2229 } |
2229 } |
2230 %}. |
2230 %}. |
2231 handle isNil ifTrue:[^ self errorNotOpen]. |
2231 handle isNil ifTrue:[^ self errorNotOpen]. |
2232 fileClosed ifTrue:[handle := nil. ^ self errorNotOpen]. |
2232 fileClosed ifTrue:[handle := nil. ^ self errorNotOpen]. |
2233 ^ self fileDescriptorOfFile:handle |
2233 ^ self fileDescriptorOfFile:handle |
2257 |
2257 |
2258 %{ |
2258 %{ |
2259 OBJ _handle = __INST(handle); |
2259 OBJ _handle = __INST(handle); |
2260 |
2260 |
2261 if (_handle != nil) { |
2261 if (_handle != nil) { |
2262 if ((__INST(handleType) == @symbol(fileHandle)) |
2262 if ((__INST(handleType) == @symbol(fileHandle)) |
2263 || (__INST(handleType) == @symbol(socketHandle))) { |
2263 || (__INST(handleType) == @symbol(socketHandle))) { |
2264 RETURN (_handle); |
2264 RETURN (_handle); |
2265 } |
2265 } |
2266 if (__INST(handleType) == @symbol(pipeFilePointer)) { |
2266 if (__INST(handleType) == @symbol(pipeFilePointer)) { |
2267 RETURN (__MKINT(fileno(__FILEVal(_handle)))); |
2267 RETURN (__MKINT(fileno(__FILEVal(_handle)))); |
2268 } |
2268 } |
2269 if ((__INST(handleType) == nil) |
2269 if ((__INST(handleType) == nil) |
2270 || (__INST(handleType) == @symbol(filePointer)) |
2270 || (__INST(handleType) == @symbol(filePointer)) |
2271 || (__INST(handleType) == @symbol(socketFilePointer)) |
2271 || (__INST(handleType) == @symbol(socketFilePointer)) |
2272 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2272 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2273 #ifdef __win32__ |
2273 #ifdef __win32__ |
2274 RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle))))); |
2274 RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle))))); |
2275 #else |
2275 #else |
2276 FILE *file = __FILEVal(_handle); |
2276 FILE *file = __FILEVal(_handle); |
2277 if (file != NULL) { |
2277 if (file != NULL) { |
2278 int fileNo = fileno(file); |
2278 int fileNo = fileno(file); |
2279 if (fileNo >= 0) { |
2279 if (fileNo >= 0) { |
2280 RETURN (__MKINT(fileNo)); |
2280 RETURN (__MKINT(fileNo)); |
2281 } |
2281 } |
2282 } |
2282 } |
2283 #endif |
2283 #endif |
2284 } |
2284 } |
2285 } |
2285 } |
2286 %}. |
2286 %}. |
2287 ^ handle |
2287 ^ handle |
2288 |
2288 |
2289 "Modified: / 07-04-2017 / 16:34:40 / cg" |
2289 "Modified: / 07-04-2017 / 16:34:40 / cg" |
2296 (what you really get is a corresponding integer). |
2296 (what you really get is a corresponding integer). |
2297 You cannot do much with the returned value |
2297 You cannot do much with the returned value |
2298 - except passing it to a primitive, for example." |
2298 - except passing it to a primitive, for example." |
2299 |
2299 |
2300 (handleType isNil or:[handleType == #filePointer]) ifTrue:[ |
2300 (handleType isNil or:[handleType == #filePointer]) ifTrue:[ |
2301 ^ handle |
2301 ^ handle |
2302 ]. |
2302 ]. |
2303 ^ self error:'not a FILE*' |
2303 ^ self error:'not a FILE*' |
2304 ! |
2304 ! |
2305 |
2305 |
2306 handle |
2306 handle |
2353 "turn on or off CRLF sending (instead of LF only) - default is off. |
2353 "turn on or off CRLF sending (instead of LF only) - default is off. |
2354 This method is provided for backward compatibility - see #eolMode: |
2354 This method is provided for backward compatibility - see #eolMode: |
2355 which offers another choice." |
2355 which offers another choice." |
2356 |
2356 |
2357 aBoolean ifTrue:[ |
2357 aBoolean ifTrue:[ |
2358 eolMode := #crlf |
2358 eolMode := #crlf |
2359 ] ifFalse:[ |
2359 ] ifFalse:[ |
2360 eolMode := #nl |
2360 eolMode := #nl |
2361 ]. |
2361 ]. |
2362 ! |
2362 ! |
2363 |
2363 |
2364 writeonly |
2364 writeonly |
2365 "set access mode to writeonly" |
2365 "set access mode to writeonly" |
2381 close |
2381 close |
2382 "Close the stream. |
2382 "Close the stream. |
2383 No error if the stream is not open." |
2383 No error if the stream is not open." |
2384 |
2384 |
2385 self isOpen ifTrue:[ |
2385 self isOpen ifTrue:[ |
2386 self unregisterForFinalization. |
2386 self unregisterForFinalization. |
2387 self isOpen ifTrue:[ |
2387 self isOpen ifTrue:[ |
2388 self closeFile. |
2388 self closeFile. |
2389 ]. |
2389 ]. |
2390 ]. |
2390 ]. |
2391 ! |
2391 ! |
2392 |
2392 |
2393 shutDown |
2393 shutDown |
2394 "close the stream - added for protocol compatibility with Socket. |
2394 "close the stream - added for protocol compatibility with Socket. |
2408 |copy| |
2408 |copy| |
2409 |
2409 |
2410 copy := super copy. |
2410 copy := super copy. |
2411 copy dupFd. |
2411 copy dupFd. |
2412 self isPositionable ifTrue:[ |
2412 self isPositionable ifTrue:[ |
2413 copy position:position. |
2413 copy position:position. |
2414 ]. |
2414 ]. |
2415 copy registerForFinalization. |
2415 copy registerForFinalization. |
2416 ^ copy |
2416 ^ copy |
2417 |
2417 |
2418 " |
2418 " |
2456 "{ Pragma: +optSpace }" |
2456 "{ Pragma: +optSpace }" |
2457 |
2457 |
2458 "report an error, that the stream is already opened" |
2458 "report an error, that the stream is already opened" |
2459 |
2459 |
2460 ^ OpenError |
2460 ^ OpenError |
2461 raiseRequestWith:self |
2461 raiseRequestWith:self |
2462 errorString:' - stream is already open' |
2462 errorString:' - stream is already open' |
2463 |
2463 |
2464 " |
2464 " |
2465 self new errorAlreadyOpen |
2465 self new errorAlreadyOpen |
2466 " |
2466 " |
2467 |
2467 |
2472 "{ Pragma: +optSpace }" |
2472 "{ Pragma: +optSpace }" |
2473 |
2473 |
2474 "report an error, that the stream is in binary mode" |
2474 "report an error, that the stream is in binary mode" |
2475 |
2475 |
2476 ^ InvalidModeError |
2476 ^ InvalidModeError |
2477 raiseRequestWith:self |
2477 raiseRequestWith:self |
2478 errorString:(self class name , ' is in binary mode') |
2478 errorString:(self class name , ' is in binary mode') |
2479 "/ in:thisContext sender |
2479 "/ in:thisContext sender |
2480 |
2480 |
2481 "Modified: / 8.5.1999 / 20:12:43 / cg" |
2481 "Modified: / 8.5.1999 / 20:12:43 / cg" |
2482 ! |
2482 ! |
2483 |
2483 |
2484 errorNotBinary |
2484 errorNotBinary |
2485 "{ Pragma: +optSpace }" |
2485 "{ Pragma: +optSpace }" |
2486 |
2486 |
2487 "report an error, that the stream is not in binary mode" |
2487 "report an error, that the stream is not in binary mode" |
2488 |
2488 |
2489 ^ InvalidModeError |
2489 ^ InvalidModeError |
2490 raiseRequestWith:self |
2490 raiseRequestWith:self |
2491 errorString:(self class name , ' is not in binary mode') |
2491 errorString:(self class name , ' is not in binary mode') |
2492 "/ in:thisContext sender |
2492 "/ in:thisContext sender |
2493 |
2493 |
2494 "Modified: / 8.5.1999 / 20:12:40 / cg" |
2494 "Modified: / 8.5.1999 / 20:12:40 / cg" |
2495 ! |
2495 ! |
2496 |
2496 |
2497 errorNotBuffered |
2497 errorNotBuffered |
2498 "{ Pragma: +optSpace }" |
2498 "{ Pragma: +optSpace }" |
2499 |
2499 |
2500 "report an error, that the stream is not in buffered mode" |
2500 "report an error, that the stream is not in buffered mode" |
2501 |
2501 |
2502 ^ StreamError |
2502 ^ StreamError |
2503 raiseRequestWith:self |
2503 raiseRequestWith:self |
2504 errorString:(self class name , ' is unbuffered - operation not allowed') |
2504 errorString:(self class name , ' is unbuffered - operation not allowed') |
2505 "/ in:thisContext sender |
2505 "/ in:thisContext sender |
2506 |
2506 |
2507 "Modified: / 8.5.1999 / 20:12:36 / cg" |
2507 "Modified: / 8.5.1999 / 20:12:36 / cg" |
2508 ! |
2508 ! |
2509 |
2509 |
2510 errorReadOnly |
2510 errorReadOnly |
2561 which is no longer available and has been mounted soft)" |
2561 which is no longer available and has been mounted soft)" |
2562 |
2562 |
2563 "{ Pragma: +optSpace }" |
2563 "{ Pragma: +optSpace }" |
2564 |
2564 |
2565 ^ StreamIOError newException |
2565 ^ StreamIOError newException |
2566 errorCode:errorNumber; |
2566 errorCode:errorNumber; |
2567 osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber); |
2567 osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber); |
2568 parameter:self; |
2568 parameter:self; |
2569 raiseRequest |
2569 raiseRequest |
2570 |
2570 |
2571 "Modified: / 8.5.1999 / 20:12:16 / cg" |
2571 "Modified: / 8.5.1999 / 20:12:16 / cg" |
2572 ! |
2572 ! |
2573 |
2573 |
2574 lastErrorNumber |
2574 lastErrorNumber |
2579 |
2579 |
2580 lastErrorString |
2580 lastErrorString |
2581 "return a message string describing the last error" |
2581 "return a message string describing the last error" |
2582 |
2582 |
2583 (lastErrorNumber isNil or:[lastErrorNumber == 0]) ifTrue:[ |
2583 (lastErrorNumber isNil or:[lastErrorNumber == 0]) ifTrue:[ |
2584 ^ 'I/O error' |
2584 ^ 'I/O error' |
2585 ]. |
2585 ]. |
2586 ^ OperatingSystem errorTextForNumber:lastErrorNumber |
2586 ^ OperatingSystem errorTextForNumber:lastErrorNumber |
2587 ! |
2587 ! |
2588 |
2588 |
2589 lastErrorSymbol |
2589 lastErrorSymbol |
2608 |exClass errorHolder| |
2608 |exClass errorHolder| |
2609 |
2609 |
2610 errorHolder := OperatingSystem errorHolderForNumber:errorNumber. |
2610 errorHolder := OperatingSystem errorHolderForNumber:errorNumber. |
2611 |
2611 |
2612 exClass := (errorHolder errorCategory == #nonexistentSignal) |
2612 exClass := (errorHolder errorCategory == #nonexistentSignal) |
2613 ifTrue:[ FileDoesNotExistException ] |
2613 ifTrue:[ FileDoesNotExistException ] |
2614 ifFalse:[ OpenError ]. |
2614 ifFalse:[ OpenError ]. |
2615 |
2615 |
2616 ^ exClass newException |
2616 ^ exClass newException |
2617 errorCode:errorNumber; |
2617 errorCode:errorNumber; |
2618 osErrorHolder:errorHolder; |
2618 osErrorHolder:errorHolder; |
2619 "/ cg: initialized lazily - see OpenError>>#description |
2619 "/ cg: initialized lazily - see OpenError>>#description |
2620 "/ errorString:(' : ' , errorHolder errorString); |
2620 "/ errorString:(' : ' , errorHolder errorString); |
2621 parameter:self; |
2621 parameter:self; |
2622 raiseRequest |
2622 raiseRequest |
2623 "/ in:thisContext sender |
2623 "/ in:thisContext sender |
2624 |
2624 |
2625 "Modified: / 09-09-2011 / 07:22:49 / cg" |
2625 "Modified: / 09-09-2011 / 07:22:49 / cg" |
2626 ! |
2626 ! |
2627 |
2627 |
2628 readError |
2628 readError |
2637 "report an error, that some read error occurred" |
2637 "report an error, that some read error occurred" |
2638 |
2638 |
2639 "{ Pragma: +optSpace }" |
2639 "{ Pragma: +optSpace }" |
2640 |
2640 |
2641 ^ ReadError newException |
2641 ^ ReadError newException |
2642 errorCode:errorNumber; |
2642 errorCode:errorNumber; |
2643 osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber); |
2643 osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber); |
2644 parameter:self; |
2644 parameter:self; |
2645 raiseRequest |
2645 raiseRequest |
2646 ! |
2646 ! |
2647 |
2647 |
2648 writeError |
2648 writeError |
2649 "report an error, that some write error occurred" |
2649 "report an error, that some write error occurred" |
2650 |
2650 |
2657 "report an error, that some write error occurred" |
2657 "report an error, that some write error occurred" |
2658 |
2658 |
2659 "{ Pragma: +optSpace }" |
2659 "{ Pragma: +optSpace }" |
2660 |
2660 |
2661 ^ WriteError newException |
2661 ^ WriteError newException |
2662 errorCode:errorNumber; |
2662 errorCode:errorNumber; |
2663 osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber); |
2663 osErrorHolder:(OperatingSystem errorHolderForNumber:errorNumber); |
2664 parameter:self; |
2664 parameter:self; |
2665 raiseRequest |
2665 raiseRequest |
2666 ! ! |
2666 ! ! |
2667 |
2667 |
2668 !ExternalStream methodsFor:'finalization'! |
2668 !ExternalStream methodsFor:'finalization'! |
2669 |
2669 |
2670 beExecutor |
2670 beExecutor |
2680 "return a copy for finalization-registration; |
2680 "return a copy for finalization-registration; |
2681 since all we need at finalization time is the fileDescriptor, |
2681 since all we need at finalization time is the fileDescriptor, |
2682 a cheaper copy is possible." |
2682 a cheaper copy is possible." |
2683 |
2683 |
2684 ^ self class basicNew |
2684 ^ self class basicNew |
2685 beExecutor; |
2685 beExecutor; |
2686 setAccessor:handleType to:handle; |
2686 setAccessor:handleType to:handle; |
2687 yourself. |
2687 yourself. |
2688 |
2688 |
2689 "Modified: / 23-04-2018 / 18:34:38 / stefan" |
2689 "Modified: / 23-04-2018 / 18:34:38 / stefan" |
2690 ! |
2690 ! |
2691 |
2691 |
2692 finalize |
2692 finalize |
2701 |
2701 |
2702 registerForFinalization |
2702 registerForFinalization |
2703 |
2703 |
2704 "keep myself in newSpace, so it will be finalized early" |
2704 "keep myself in newSpace, so it will be finalized early" |
2705 Lobby size < MaxNonTenurableExecutors ifTrue:[ |
2705 Lobby size < MaxNonTenurableExecutors ifTrue:[ |
2706 ObjectMemory preventTenureOf:self. |
2706 ObjectMemory preventTenureOf:self. |
2707 ]. |
2707 ]. |
2708 Lobby register:self. |
2708 Lobby register:self. |
2709 ! |
2709 ! |
2710 |
2710 |
2711 unregisterForFinalization |
2711 unregisterForFinalization |
2755 if ((__INST(handleType) == nil) |
2755 if ((__INST(handleType) == nil) |
2756 || (__INST(handleType) == @symbol(filePointer)) |
2756 || (__INST(handleType) == @symbol(filePointer)) |
2757 || (__INST(handleType) == @symbol(socketFilePointer)) |
2757 || (__INST(handleType) == @symbol(socketFilePointer)) |
2758 || (__INST(handleType) == @symbol(socketHandle)) |
2758 || (__INST(handleType) == @symbol(socketHandle)) |
2759 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2759 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2760 if (((fp = __INST(handle)) != nil) |
2760 if (((fp = __INST(handle)) != nil) |
2761 && (__INST(mode) != @symbol(writeonly)) |
2761 && (__INST(mode) != @symbol(writeonly)) |
2762 && (__INST(binary) != true) |
2762 && (__INST(binary) != true) |
2763 ) { |
2763 ) { |
2764 f = __FILEVal(fp); |
2764 f = __FILEVal(fp); |
2765 buffer[0] = '\0'; |
2765 buffer[0] = '\0'; |
2766 |
2766 |
2767 _buffered = (__INST(buffered) == true); |
2767 _buffered = (__INST(buffered) == true); |
2768 if (_buffered) { |
2768 if (_buffered) { |
2769 __READING__(f); |
2769 __READING__(f); |
2770 } |
2770 } |
2771 |
2771 |
2772 rslt = nextPtr = buffer; |
2772 rslt = nextPtr = buffer; |
2773 limit = buffer + sizeof(buffer) - 2; |
2773 limit = buffer + sizeof(buffer) - 2; |
2774 |
2774 |
2775 for (;;) { |
2775 for (;;) { |
2776 __READBYTE__(ret, f, nextPtr, _buffered, __INST(handleType)); |
2776 __READBYTE__(ret, f, nextPtr, _buffered, __INST(handleType)); |
2777 if (ret <= 0) { |
2777 if (ret <= 0) { |
2778 if (nextPtr == buffer) |
2778 if (nextPtr == buffer) |
2779 rslt = NULL; |
2779 rslt = NULL; |
2780 if (ret == 0) { |
2780 if (ret == 0) { |
2781 __INST(hitEOF) = true; |
2781 __INST(hitEOF) = true; |
2782 break; |
2782 break; |
2783 } else { |
2783 } else { |
2784 error = __mkSmallInteger(__threadErrno); |
2784 error = __mkSmallInteger(__threadErrno); |
2785 goto err; |
2785 goto err; |
2786 } |
2786 } |
2787 } |
2787 } |
2788 |
2788 |
2789 if (*nextPtr == '\n') { |
2789 if (*nextPtr == '\n') { |
2790 cutOff = 1; |
2790 cutOff = 1; |
2791 *nextPtr = '\0'; |
2791 *nextPtr = '\0'; |
2792 break; |
2792 break; |
2793 } |
2793 } |
2794 if (*nextPtr == '\r') { |
2794 if (*nextPtr == '\r') { |
2795 char peekChar; |
2795 char peekChar; |
2796 |
2796 |
2797 /* |
2797 /* |
2798 * peek ahead for a newLine ... |
2798 * peek ahead for a newLine ... |
2799 */ |
2799 */ |
2800 __READBYTE__(ret, f, &peekChar, _buffered, __INST(handleType)); |
2800 __READBYTE__(ret, f, &peekChar, _buffered, __INST(handleType)); |
2801 if (ret <= 0) { |
2801 if (ret <= 0) { |
2802 cutOff = 1; |
2802 cutOff = 1; |
2803 *nextPtr = '\0'; |
2803 *nextPtr = '\0'; |
2804 if (ret == 0) { |
2804 if (ret == 0) { |
2805 __INST(hitEOF) = true; |
2805 __INST(hitEOF) = true; |
2806 break; |
2806 break; |
2807 } |
2807 } |
2808 error = __mkSmallInteger(__threadErrno); |
2808 error = __mkSmallInteger(__threadErrno); |
2809 goto err; |
2809 goto err; |
2810 } |
2810 } |
2811 |
2811 |
2812 if (peekChar == '\n') { |
2812 if (peekChar == '\n') { |
2813 cutOff = 2; |
2813 cutOff = 2; |
2814 *nextPtr = '\0'; |
2814 *nextPtr = '\0'; |
2815 break; |
2815 break; |
2816 } |
2816 } |
2817 |
2817 |
2818 __UNGETC__(peekChar, f, _buffered); |
2818 __UNGETC__(peekChar, f, _buffered); |
2819 |
2819 |
2820 cutOff = 1; |
2820 cutOff = 1; |
2821 *nextPtr = '\0'; |
2821 *nextPtr = '\0'; |
2822 break; |
2822 break; |
2823 } |
2823 } |
2824 |
2824 |
2825 nextPtr++; |
2825 nextPtr++; |
2826 if (nextPtr >= limit) { |
2826 if (nextPtr >= limit) { |
2827 *nextPtr = '\0'; |
2827 *nextPtr = '\0'; |
2828 lineTooLong = 1; |
2828 lineTooLong = 1; |
2829 // signalled below anyway; so no need to print on stderr |
2829 break; |
2830 #if 0 |
2830 } |
2831 if (@global(InfoPrinting) == true) { |
2831 } |
2832 fprintf(stderr, "ExtStream [warning]: line truncated in nextLine\n"); |
2832 |
2833 } |
2833 if (rslt != NULL) { |
2834 #endif |
2834 len = nextPtr-buffer; |
2835 break; |
2835 |
2836 } |
2836 if (__isSmallInteger(__INST(position))) { |
2837 } |
2837 INT np = __intVal(__INST(position)) + len + cutOff; |
2838 |
2838 OBJ t; |
2839 if (rslt != NULL) { |
2839 |
2840 len = nextPtr-buffer; |
2840 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
2841 |
2841 } else { |
2842 if (__isSmallInteger(__INST(position))) { |
2842 __INST(position) = nil; /* i.e. do not know */ |
2843 INT np = __intVal(__INST(position)) + len + cutOff; |
2843 } |
2844 OBJ t; |
2844 /* remove any EOL character */ |
2845 |
2845 if (len != 0) { |
2846 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
2846 if (buffer[len-1] == '\n') { |
2847 } else { |
2847 buffer[--len] = '\0'; |
2848 __INST(position) = nil; /* i.e. do not know */ |
2848 } |
2849 } |
2849 if ((len != 0) && (buffer[len-1] == '\r')) { |
2850 /* remove any EOL character */ |
2850 buffer[--len] = '\0'; |
2851 if (len != 0) { |
2851 } |
2852 if (buffer[len-1] == '\n') { |
2852 } |
2853 buffer[--len] = '\0'; |
2853 line = __MKSTRING_L(buffer, len); |
2854 } |
2854 if (! lineTooLong) { |
2855 if ((len != 0) && (buffer[len-1] == '\r')) { |
2855 RETURN ( line ); |
2856 buffer[--len] = '\0'; |
2856 } |
2857 } |
2857 } |
2858 } |
2858 } |
2859 line = __MKSTRING_L(buffer, len); |
|
2860 if (! lineTooLong) { |
|
2861 RETURN ( line ); |
|
2862 } |
|
2863 } |
|
2864 } |
|
2865 } |
2859 } |
2866 err: ; |
2860 err: ; |
2867 %}. |
2861 %}. |
2868 line notNil ifTrue:[ |
2862 line notNil ifTrue:[ |
2869 "/ the line as read is longer than 32k characters (boy - what a line) |
2863 "/ the line as read is longer than 32k characters (boy - what a line) |
2870 "/ The exception could be handled by reading more and returning the |
2864 "/ The exception raised below can be handled to ask the user |
2871 "/ concatenation in your exception handler (the receiver and the partial |
2865 "/ and to read more and return the concatenation from the exception handler |
2872 "/ line are passed as parameter) |
2866 "/ (the receiver and the partial line are passed as parameter) |
2873 |
2867 "/ If unhandled, we do exactly that: read the rest and return the concatenation |
2874 LineTooLongErrorSignal isHandled ifTrue:[ |
2868 "/ i.e. the full line - whatever its size is. |
2875 ^ LineTooLongErrorSignal |
2869 |
2876 raiseRequestWith:(Array with:self with:line) |
2870 LineTooLongErrorSignal isHandled ifTrue:[ |
2877 errorString:('line too long read error') |
2871 ^ LineTooLongErrorSignal |
2878 ]. |
2872 raiseRequestWith:(Array with:self with:line) |
2879 'ExternalStream [warning]: line truncated in nextLine' infoPrintCR. |
2873 errorString:('line too long read error') |
2880 ^ line , self nextLine |
2874 ]. |
2875 'ExternalStream [info]: very long line in nextLine' infoPrintCR. |
|
2876 ^ line , self nextLine |
|
2881 ]. |
2877 ]. |
2882 |
2878 |
2883 hitEOF ifTrue:[^ self pastEndRead]. |
2879 hitEOF ifTrue:[^ self pastEndRead]. |
2884 error notNil ifTrue:[ |
2880 error notNil ifTrue:[ |
2885 lastErrorNumber := error. |
2881 lastErrorNumber := error. |
2886 ^ self readError:error |
2882 ^ self readError:error |
2887 ]. |
2883 ]. |
2888 handle isNil ifTrue:[^ self errorNotOpen]. |
2884 handle isNil ifTrue:[^ self errorNotOpen]. |
2889 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
2885 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
2890 binary ifTrue:[^ self errorBinary]. |
2886 binary ifTrue:[^ self errorBinary]. |
2891 ^ super nextLine |
2887 ^ super nextLine |
2903 if ((__INST(handleType) == nil) |
2899 if ((__INST(handleType) == nil) |
2904 || (__INST(handleType) == @symbol(filePointer)) |
2900 || (__INST(handleType) == @symbol(filePointer)) |
2905 || (__INST(handleType) == @symbol(socketFilePointer)) |
2901 || (__INST(handleType) == @symbol(socketFilePointer)) |
2906 || (__INST(handleType) == @symbol(socketHandle)) |
2902 || (__INST(handleType) == @symbol(socketHandle)) |
2907 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2903 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
2908 if (((fp = __INST(handle)) != nil) |
2904 if (((fp = __INST(handle)) != nil) |
2909 && (__INST(mode) != @symbol(readonly)) |
2905 && (__INST(mode) != @symbol(readonly)) |
2910 && (__INST(binary) != true) |
2906 && (__INST(binary) != true) |
2911 && __isStringLike(aString) |
2907 && __isStringLike(aString) |
2912 ) { |
2908 ) { |
2913 int _buffered = (__INST(buffered) == true); |
2909 int _buffered = (__INST(buffered) == true); |
2914 int len = __stringSize(aString); |
2910 int len = __stringSize(aString); |
2915 int cnt, len1; |
2911 int cnt, len1; |
2916 FILEPOINTER f = __FILEVal(fp); |
2912 FILEPOINTER f = __FILEVal(fp); |
2917 char *cp; |
2913 char *cp; |
2918 int o_offs; |
2914 int o_offs; |
2919 |
2915 |
2920 if (_buffered) { |
2916 if (_buffered) { |
2921 __WRITING__(f) |
2917 __WRITING__(f) |
2922 } |
2918 } |
2923 #ifdef __win32__ |
2919 #ifdef __win32__ |
2924 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
2920 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
2925 cnt = __win32_fwrite(__stringVal(aString), 1, len, f); |
2921 cnt = __win32_fwrite(__stringVal(aString), 1, len, f); |
2926 } else |
2922 } else |
2927 #endif |
2923 #endif |
2928 { |
2924 { |
2929 o_offs = (char *)__stringVal(aString)-(char *)aString; |
2925 o_offs = (char *)__stringVal(aString)-(char *)aString; |
2930 __WRITEBYTES_OBJ__(cnt, f, aString, o_offs, len, _buffered, __INST(handleType)); |
2926 __WRITEBYTES_OBJ__(cnt, f, aString, o_offs, len, _buffered, __INST(handleType)); |
2931 } |
2927 } |
2932 if (cnt == len) { |
2928 if (cnt == len) { |
2933 OBJ mode = __INST(eolMode); |
2929 OBJ mode = __INST(eolMode); |
2934 |
2930 |
2935 len1 = len; |
2931 len1 = len; |
2936 |
2932 |
2937 if (mode == @symbol(cr)) { |
2933 if (mode == @symbol(cr)) { |
2938 cp = "\r"; len = 1; |
2934 cp = "\r"; len = 1; |
2939 } else if (mode == @symbol(crlf)) { |
2935 } else if (mode == @symbol(crlf)) { |
2940 cp = "\r\n"; len = 2; |
2936 cp = "\r\n"; len = 2; |
2941 } else if (mode == @symbol(eot)) { |
2937 } else if (mode == @symbol(eot)) { |
2942 cp = "\004"; len = 1; |
2938 cp = "\004"; len = 1; |
2943 } else if (mode == @symbol(etx)) { |
2939 } else if (mode == @symbol(etx)) { |
2944 cp = "\003"; len = 1; |
2940 cp = "\003"; len = 1; |
2945 } else { |
2941 } else { |
2946 cp = "\n"; len = 1; |
2942 cp = "\n"; len = 1; |
2947 } |
2943 } |
2948 #ifdef __win32__ |
2944 #ifdef __win32__ |
2949 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
2945 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
2950 cnt = __win32_fwrite(cp, 1, len, f); |
2946 cnt = __win32_fwrite(cp, 1, len, f); |
2951 } else |
2947 } else |
2952 #endif |
2948 #endif |
2953 { |
2949 { |
2954 __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType)); |
2950 __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType)); |
2955 } |
2951 } |
2956 if (cnt > 0) { |
2952 if (cnt > 0) { |
2957 if (__isSmallInteger(__INST(position))) { |
2953 if (__isSmallInteger(__INST(position))) { |
2958 INT np = __intVal(__INST(position)) + len1 + cnt; |
2954 INT np = __intVal(__INST(position)) + len1 + cnt; |
2959 OBJ t; |
2955 OBJ t; |
2960 |
2956 |
2961 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
2957 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
2962 } else { |
2958 } else { |
2963 __INST(position) = nil; /* i.e. do not know */ |
2959 __INST(position) = nil; /* i.e. do not know */ |
2964 } |
2960 } |
2965 RETURN ( self ); |
2961 RETURN ( self ); |
2966 } |
2962 } |
2967 } |
2963 } |
2968 error = __mkSmallInteger(__threadErrno); |
2964 error = __mkSmallInteger(__threadErrno); |
2969 } |
2965 } |
2970 } |
2966 } |
2971 %}. |
2967 %}. |
2972 error notNil ifTrue:[ |
2968 error notNil ifTrue:[ |
2973 lastErrorNumber := error. |
2969 lastErrorNumber := error. |
2974 self writeError:error. |
2970 self writeError:error. |
2975 ^ self |
2971 ^ self |
2976 ]. |
2972 ]. |
2977 super nextPutLine:aString. |
2973 super nextPutLine:aString. |
2978 ! |
2974 ! |
2979 |
2975 |
2980 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil |
2976 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil |
2985 If aStringOrNil is nil or not matched, copy proceeds to the end." |
2981 If aStringOrNil is nil or not matched, copy proceeds to the end." |
2986 |
2982 |
2987 |line| |
2983 |line| |
2988 |
2984 |
2989 [aStream atEnd] whileFalse:[ |
2985 [aStream atEnd] whileFalse:[ |
2990 line := aStream nextLine. |
2986 line := aStream nextLine. |
2991 line isNil ifTrue:[ |
2987 line isNil ifTrue:[ |
2992 ^ self. |
2988 ^ self. |
2993 ]. |
2989 ]. |
2994 self nextPutLine:line. |
2990 self nextPutLine:line. |
2995 (aStringOrNil notNil and:[line startsWith:aStringOrNil]) ifTrue:[ |
2991 (aStringOrNil notNil and:[line startsWith:aStringOrNil]) ifTrue:[ |
2996 ^ self |
2992 ^ self |
2997 ] |
2993 ] |
2998 ]. |
2994 ]. |
2999 ! |
2995 ! |
3000 |
2996 |
3001 peekForLineStartingWith:aString |
2997 peekForLineStartingWith:aString |
3002 "read ahead for next line starting with aString; |
2998 "read ahead for next line starting with aString; |
3012 binary ifTrue:[^ self errorBinary]. |
3008 binary ifTrue:[^ self errorBinary]. |
3013 buffered ifFalse:[^ self errorNotBuffered]. |
3009 buffered ifFalse:[^ self errorNotBuffered]. |
3014 |
3010 |
3015 firstPos := self position. |
3011 firstPos := self position. |
3016 [self atEnd] whileFalse:[ |
3012 [self atEnd] whileFalse:[ |
3017 lastPos := self position. |
3013 lastPos := self position. |
3018 line := self nextLine. |
3014 line := self nextLine. |
3019 line isNil ifTrue:[ |
3015 line isNil ifTrue:[ |
3020 self position:firstPos. |
3016 self position:firstPos. |
3021 ^ nil |
3017 ^ nil |
3022 ]. |
3018 ]. |
3023 (line startsWith:aString) ifTrue:[ |
3019 (line startsWith:aString) ifTrue:[ |
3024 self position:lastPos. |
3020 self position:lastPos. |
3025 ^ line |
3021 ^ line |
3026 ] |
3022 ] |
3027 ]. |
3023 ]. |
3028 self position:firstPos. |
3024 self position:firstPos. |
3029 ^ nil |
3025 ^ nil |
3030 ! |
3026 ! |
3031 |
3027 |
3041 handle isNil ifTrue:[^ self errorNotOpen]. |
3037 handle isNil ifTrue:[^ self errorNotOpen]. |
3042 binary ifTrue:[^ self errorBinary]. |
3038 binary ifTrue:[^ self errorBinary]. |
3043 |
3039 |
3044 startPos := self position. |
3040 startPos := self position. |
3045 [self atEnd] whileFalse:[ |
3041 [self atEnd] whileFalse:[ |
3046 linePos := self position. |
3042 linePos := self position. |
3047 line := self nextLine. |
3043 line := self nextLine. |
3048 line notNil ifTrue:[ |
3044 line notNil ifTrue:[ |
3049 index := 1. |
3045 index := 1. |
3050 aCollectionOfStrings do:[:prefix | |
3046 aCollectionOfStrings do:[:prefix | |
3051 (line startsWith:prefix) ifTrue:[ |
3047 (line startsWith:prefix) ifTrue:[ |
3052 self position:linePos. |
3048 self position:linePos. |
3053 ^ index |
3049 ^ index |
3054 ]. |
3050 ]. |
3055 index := index + 1 |
3051 index := index + 1 |
3056 ] |
3052 ] |
3057 ] |
3053 ] |
3058 ]. |
3054 ]. |
3059 self position:startPos. |
3055 self position:startPos. |
3060 ^ nil |
3056 ^ nil |
3061 ! ! |
3057 ! ! |
3062 |
3058 |
3065 async:aBoolean |
3061 async:aBoolean |
3066 "set/clear the async attribute - if set, the availability of data on |
3062 "set/clear the async attribute - if set, the availability of data on |
3067 the receiver will trigger an ioInterrupt. |
3063 the receiver will trigger an ioInterrupt. |
3068 If cleared (which is the default) no special notification is made. |
3064 If cleared (which is the default) no special notification is made. |
3069 Notice: |
3065 Notice: |
3070 not every OS supports this |
3066 not every OS supports this |
3071 - check with OS>>supportsIOInterrupts before using" |
3067 - check with OS>>supportsIOInterrupts before using" |
3072 |
3068 |
3073 |fd| |
3069 |fd| |
3074 |
3070 |
3075 OperatingSystem supportsIOInterrupts ifFalse:[ |
3071 OperatingSystem supportsIOInterrupts ifFalse:[ |
3076 ^ self errorUnsupportedOperation |
3072 ^ self errorUnsupportedOperation |
3077 ]. |
3073 ]. |
3078 |
3074 |
3079 fd := self fileDescriptor. |
3075 fd := self fileDescriptor. |
3080 "self fileDescriptor may set handle to nil" |
3076 "self fileDescriptor may set handle to nil" |
3081 handle isNil ifTrue:[^ self errorNotOpen]. |
3077 handle isNil ifTrue:[^ self errorNotOpen]. |
3082 |
3078 |
3083 aBoolean ifTrue:[ |
3079 aBoolean ifTrue:[ |
3084 ^ OperatingSystem enableIOInterruptsOn:fd |
3080 ^ OperatingSystem enableIOInterruptsOn:fd |
3085 ]. |
3081 ]. |
3086 ^ OperatingSystem disableIOInterruptsOn:fd |
3082 ^ OperatingSystem disableIOInterruptsOn:fd |
3087 |
3083 |
3088 "Modified: 11.1.1997 / 17:50:21 / cg" |
3084 "Modified: 11.1.1997 / 17:50:21 / cg" |
3089 ! |
3085 ! |
3175 unsigned int ioNum; |
3171 unsigned int ioNum; |
3176 INT ioArg; |
3172 INT ioArg; |
3177 OBJ fp = __INST(handle); |
3173 OBJ fp = __INST(handle); |
3178 |
3174 |
3179 if (fp == nil) |
3175 if (fp == nil) |
3180 goto out; |
3176 goto out; |
3181 |
3177 |
3182 if (!__isInteger(ioctlNumber) |
3178 if (!__isInteger(ioctlNumber) |
3183 || (!__isInteger(arg) |
3179 || (!__isInteger(arg) |
3184 && (arg != nil) |
3180 && (arg != nil) |
3185 && !__isBytes(arg) |
3181 && !__isBytes(arg) |
3186 && !__isExternalBytesLike(arg) |
3182 && !__isExternalBytesLike(arg) |
3187 && !__isExternalAddress(arg))) { |
3183 && !__isExternalAddress(arg))) { |
3188 error = @symbol(badArgument); |
3184 error = @symbol(badArgument); |
3189 goto out; |
3185 goto out; |
3190 } |
3186 } |
3191 |
3187 |
3192 if (__INST(handleType) == @symbol(socketHandle)) { |
3188 if (__INST(handleType) == @symbol(socketHandle)) { |
3193 fd = (int)((SOCKET)(__FILEVal(fp))); |
3189 fd = (int)((SOCKET)(__FILEVal(fp))); |
3194 } else |
3190 } else |
3195 if ((__INST(handleType) == nil) |
3191 if ((__INST(handleType) == nil) |
3196 || (__INST(handleType) == @symbol(filePointer)) |
3192 || (__INST(handleType) == @symbol(filePointer)) |
3197 || (__INST(handleType) == @symbol(socketFilePointer)) |
3193 || (__INST(handleType) == @symbol(socketFilePointer)) |
3198 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3194 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3199 fd = fileno(__FILEVal(fp)); |
3195 fd = fileno(__FILEVal(fp)); |
3200 } else { |
3196 } else { |
3201 error = @symbol(badHandleType); |
3197 error = @symbol(badHandleType); |
3202 goto out; |
3198 goto out; |
3203 } |
3199 } |
3204 |
3200 |
3205 ioNum = __unsignedLongIntVal(ioctlNumber); |
3201 ioNum = __unsignedLongIntVal(ioctlNumber); |
3206 |
3202 |
3207 __BEGIN_INTERRUPTABLE__ |
3203 __BEGIN_INTERRUPTABLE__ |
3208 do { |
3204 do { |
3209 __threadErrno = 0; |
3205 __threadErrno = 0; |
3210 if (arg == nil) { |
3206 if (arg == nil) { |
3211 ioArg = 0; |
3207 ioArg = 0; |
3212 } else if (__isSmallInteger(arg)) { |
3208 } else if (__isSmallInteger(arg)) { |
3213 ioArg = __intVal(arg); |
3209 ioArg = __intVal(arg); |
3214 } else if (__isInteger(arg)) { |
3210 } else if (__isInteger(arg)) { |
3215 ioArg = __unsignedLongIntVal(arg); |
3211 ioArg = __unsignedLongIntVal(arg); |
3216 } else if (__isExternalBytesLike(arg)) { |
3212 } else if (__isExternalBytesLike(arg)) { |
3217 ioArg = (INT)(__externalBytesAddress(arg)); |
3213 ioArg = (INT)(__externalBytesAddress(arg)); |
3218 } else if (__isExternalAddress(arg)) { |
3214 } else if (__isExternalAddress(arg)) { |
3219 ioArg = (INT)(__externalAddressVal(arg)); |
3215 ioArg = (INT)(__externalAddressVal(arg)); |
3220 } else { |
3216 } else { |
3221 ioArg = (INT)(__ByteArrayInstPtr(arg)->ba_element); |
3217 ioArg = (INT)(__ByteArrayInstPtr(arg)->ba_element); |
3222 } |
3218 } |
3223 ret = ioctl(fd, ioNum, ioArg); |
3219 ret = ioctl(fd, ioNum, ioArg); |
3224 } while (ret < 0 && __threadErrno == EINTR); |
3220 } while (ret < 0 && __threadErrno == EINTR); |
3225 __END_INTERRUPTABLE__ |
3221 __END_INTERRUPTABLE__ |
3226 |
3222 |
3227 if (ret >= 0) { |
3223 if (ret >= 0) { |
3228 RETURN ( __mkSmallInteger(ret) ); |
3224 RETURN ( __mkSmallInteger(ret) ); |
3229 } |
3225 } |
3230 error = __mkSmallInteger(__threadErrno); |
3226 error = __mkSmallInteger(__threadErrno); |
3231 #endif |
3227 #endif |
3232 |
3228 |
3233 out:; |
3229 out:; |
3234 %}. |
3230 %}. |
3235 error notNil ifTrue:[ |
3231 error notNil ifTrue:[ |
3236 lastErrorNumber := error. |
3232 lastErrorNumber := error. |
3237 ^ self ioError:error. |
3233 ^ self ioError:error. |
3238 ]. |
3234 ]. |
3239 handle isNil ifTrue:[^ self errorNotOpen]. |
3235 handle isNil ifTrue:[^ self errorNotOpen]. |
3240 |
3236 |
3241 "/ the system does not support ioctl (MSDOS or VMS) |
3237 "/ the system does not support ioctl (MSDOS or VMS) |
3242 ^ self errorUnsupportedOperation |
3238 ^ self errorUnsupportedOperation |
3266 int fd; |
3262 int fd; |
3267 int ret; |
3263 int ret; |
3268 OBJ fp = __INST(handle); |
3264 OBJ fp = __INST(handle); |
3269 |
3265 |
3270 if (fp == nil) |
3266 if (fp == nil) |
3271 goto out; |
3267 goto out; |
3272 |
3268 |
3273 if (__INST(handleType) == @symbol(socketHandle)) { |
3269 if (__INST(handleType) == @symbol(socketHandle)) { |
3274 // syncing a socket to disk ? |
3270 // syncing a socket to disk ? |
3275 error = @symbol(badHandleType); |
3271 error = @symbol(badHandleType); |
3276 goto out; |
3272 goto out; |
3277 // fd = __FILEVal(fp); |
3273 // fd = __FILEVal(fp); |
3278 } else |
3274 } else |
3279 if ((__INST(handleType) == nil) |
3275 if ((__INST(handleType) == nil) |
3280 || (__INST(handleType) == @symbol(filePointer)) |
3276 || (__INST(handleType) == @symbol(filePointer)) |
3281 || (__INST(handleType) == @symbol(socketFilePointer)) |
3277 || (__INST(handleType) == @symbol(socketFilePointer)) |
3282 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3278 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3283 fd = fileno(__FILEVal(fp)); |
3279 fd = fileno(__FILEVal(fp)); |
3284 } else { |
3280 } else { |
3285 error = @symbol(badHandleType); |
3281 error = @symbol(badHandleType); |
3286 goto out; |
3282 goto out; |
3287 } |
3283 } |
3288 |
3284 |
3289 #ifdef __win32__ |
3285 #ifdef __win32__ |
3290 __threadErrno = 0; |
3286 __threadErrno = 0; |
3291 ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fd)); |
3287 ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fd)); |
3292 if (ret) { |
3288 if (ret) { |
3293 RETURN (self); |
3289 RETURN (self); |
3294 } |
3290 } |
3295 #else |
3291 #else |
3296 __BEGIN_INTERRUPTABLE__ |
3292 __BEGIN_INTERRUPTABLE__ |
3297 do { |
3293 do { |
3298 ret = fsync(fd); |
3294 ret = fsync(fd); |
3299 } while ((ret < 0) && (__threadErrno == EINTR)); |
3295 } while ((ret < 0) && (__threadErrno == EINTR)); |
3300 __END_INTERRUPTABLE__ |
3296 __END_INTERRUPTABLE__ |
3301 |
3297 |
3302 if (ret >= 0) { |
3298 if (ret >= 0) { |
3303 RETURN (self); |
3299 RETURN (self); |
3304 } |
3300 } |
3305 #endif /* ! __win32__ */ |
3301 #endif /* ! __win32__ */ |
3306 error = __mkSmallInteger(__threadErrno); |
3302 error = __mkSmallInteger(__threadErrno); |
3307 #endif /* ! __openVMS__ */ |
3303 #endif /* ! __openVMS__ */ |
3308 out:; |
3304 out:; |
3309 %}. |
3305 %}. |
3310 error notNil ifTrue:[ |
3306 error notNil ifTrue:[ |
3311 lastErrorNumber := error. |
3307 lastErrorNumber := error. |
3312 self ioError:error. |
3308 self ioError:error. |
3313 ^ self. |
3309 ^ self. |
3314 ]. |
3310 ]. |
3315 handle isNil ifTrue:[self errorNotOpen]. |
3311 handle isNil ifTrue:[self errorNotOpen]. |
3316 |
3312 |
3317 " |
3313 " |
3318 |f| |
3314 |f| |
3319 f := 'x' asFilename writeStream. |
3315 f := 'x' asFilename writeStream. |
3320 f nextPutAll:'hallo'; sync; syncData; close |
3316 f nextPutAll:'hallo'; sync; syncData; close |
3321 " |
3317 " |
3322 ! |
3318 ! |
3323 |
3319 |
3324 syncData |
3320 syncData |
3325 "make sure, that the OS writes cached data to the disk. |
3321 "make sure, that the OS writes cached data to the disk. |
3335 int fd; |
3331 int fd; |
3336 int ret; |
3332 int ret; |
3337 OBJ fp = __INST(handle); |
3333 OBJ fp = __INST(handle); |
3338 |
3334 |
3339 if (fp == nil) |
3335 if (fp == nil) |
3340 goto out; |
3336 goto out; |
3341 |
3337 |
3342 if (__INST(handleType) == @symbol(socketHandle)) { |
3338 if (__INST(handleType) == @symbol(socketHandle)) { |
3343 // syncing a socket to disk ? |
3339 // syncing a socket to disk ? |
3344 error = @symbol(badHandleType); |
3340 error = @symbol(badHandleType); |
3345 goto out; |
3341 goto out; |
3346 // fd = __FILEVal(fp); |
3342 // fd = __FILEVal(fp); |
3347 } else |
3343 } else |
3348 if ((__INST(handleType) == nil) |
3344 if ((__INST(handleType) == nil) |
3349 || (__INST(handleType) == @symbol(filePointer)) |
3345 || (__INST(handleType) == @symbol(filePointer)) |
3350 || (__INST(handleType) == @symbol(socketFilePointer)) |
3346 || (__INST(handleType) == @symbol(socketFilePointer)) |
3351 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3347 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3352 fd = fileno(__FILEVal(fp)); |
3348 fd = fileno(__FILEVal(fp)); |
3353 } else { |
3349 } else { |
3354 error = @symbol(badHandleType); |
3350 error = @symbol(badHandleType); |
3355 goto out; |
3351 goto out; |
3356 } |
3352 } |
3357 |
3353 |
3358 #ifdef __win32__ |
3354 #ifdef __win32__ |
3359 __threadErrno = 0; |
3355 __threadErrno = 0; |
3360 ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fd)); |
3356 ret = __STX_API_NOINT_CALL1( "FlushFileBuffers", FlushFileBuffers, _get_osfhandle(fd)); |
3361 if (ret) { |
3357 if (ret) { |
3362 RETURN (self); |
3358 RETURN (self); |
3363 } |
3359 } |
3364 #else |
3360 #else |
3365 __BEGIN_INTERRUPTABLE__ |
3361 __BEGIN_INTERRUPTABLE__ |
3366 do { |
3362 do { |
3367 ret = fdatasync(fd); |
3363 ret = fdatasync(fd); |
3368 } while ((ret < 0) && (__threadErrno == EINTR)); |
3364 } while ((ret < 0) && (__threadErrno == EINTR)); |
3369 __END_INTERRUPTABLE__ |
3365 __END_INTERRUPTABLE__ |
3370 |
3366 |
3371 if (ret >= 0) { |
3367 if (ret >= 0) { |
3372 RETURN (self); |
3368 RETURN (self); |
3373 } |
3369 } |
3374 #endif /* ! __win32__ */ |
3370 #endif /* ! __win32__ */ |
3375 error = __mkSmallInteger(__threadErrno); |
3371 error = __mkSmallInteger(__threadErrno); |
3376 #endif /* ! __openVMS__ */ |
3372 #endif /* ! __openVMS__ */ |
3377 out:; |
3373 out:; |
3378 %}. |
3374 %}. |
3379 |
3375 |
3380 error notNil ifTrue:[ |
3376 error notNil ifTrue:[ |
3381 lastErrorNumber := error. |
3377 lastErrorNumber := error. |
3382 self ioError:error. |
3378 self ioError:error. |
3383 ^ self. |
3379 ^ self. |
3384 ]. |
3380 ]. |
3385 handle isNil ifTrue:[^ self errorNotOpen]. |
3381 handle isNil ifTrue:[^ self errorNotOpen]. |
3386 |
3382 |
3387 "if notdef HAS_DATASYNC, fall back" |
3383 "if notdef HAS_DATASYNC, fall back" |
3388 self sync. |
3384 self sync. |
3389 |
3385 |
3390 " |
3386 " |
3391 |f| |
3387 |f| |
3392 f := 'x' asFilename writeStream. |
3388 f := 'x' asFilename writeStream. |
3393 f nextPutAll:'hallo'; sync; syncData; close |
3389 f nextPutAll:'hallo'; sync; syncData; close |
3394 " |
3390 " |
3395 ! |
3391 ! |
3396 |
3392 |
3397 tcgetattr |
3393 tcgetattr |
3398 "unix only: |
3394 "unix only: |
3421 OBJ fp = __INST(handle); |
3417 OBJ fp = __INST(handle); |
3422 struct termios t; |
3418 struct termios t; |
3423 int sz; |
3419 int sz; |
3424 |
3420 |
3425 if (fp == nil) |
3421 if (fp == nil) |
3426 goto out; |
3422 goto out; |
3427 |
3423 |
3428 if (__INST(handleType) == @symbol(socketHandle)) { |
3424 if (__INST(handleType) == @symbol(socketHandle)) { |
3429 // cg: termina attributes of a socket? |
3425 // cg: termina attributes of a socket? |
3430 error = @symbol(badHandleType); |
3426 error = @symbol(badHandleType); |
3431 goto out; |
3427 goto out; |
3432 // fd = __FILEVal(fp); |
3428 // fd = __FILEVal(fp); |
3433 } else |
3429 } else |
3434 if ((__INST(handleType) == nil) |
3430 if ((__INST(handleType) == nil) |
3435 || (__INST(handleType) == @symbol(filePointer)) |
3431 || (__INST(handleType) == @symbol(filePointer)) |
3436 || (__INST(handleType) == @symbol(socketFilePointer)) |
3432 || (__INST(handleType) == @symbol(socketFilePointer)) |
3437 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3433 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3438 fd = fileno(__FILEVal(fp)); |
3434 fd = fileno(__FILEVal(fp)); |
3439 } else { |
3435 } else { |
3440 error = @symbol(badHandleType); |
3436 error = @symbol(badHandleType); |
3441 goto out; |
3437 goto out; |
3442 } |
3438 } |
3443 |
3439 |
3444 __BEGIN_INTERRUPTABLE__ |
3440 __BEGIN_INTERRUPTABLE__ |
3445 do { |
3441 do { |
3446 __threadErrno = 0; |
3442 __threadErrno = 0; |
3447 _ret = tcgetattr(fd, &t); |
3443 _ret = tcgetattr(fd, &t); |
3448 } while (_ret < 0 && __threadErrno == EINTR); |
3444 } while (_ret < 0 && __threadErrno == EINTR); |
3449 __END_INTERRUPTABLE__ |
3445 __END_INTERRUPTABLE__ |
3450 |
3446 |
3451 if (_ret < 0) { |
3447 if (_ret < 0) { |
3452 error = __mkSmallInteger(__threadErrno); |
3448 error = __mkSmallInteger(__threadErrno); |
3453 } |
3449 } |
3454 ignbrk = t.c_iflag & IGNBRK ? true : false; |
3450 ignbrk = t.c_iflag & IGNBRK ? true : false; |
3455 brkint = t.c_iflag & BRKINT ? true : false; |
3451 brkint = t.c_iflag & BRKINT ? true : false; |
3456 ignpar = t.c_iflag & IGNPAR ? true : false; |
3452 ignpar = t.c_iflag & IGNPAR ? true : false; |
3457 parmrk = t.c_iflag & PARMRK ? true : false; |
3453 parmrk = t.c_iflag & PARMRK ? true : false; |
3483 onocr = t.c_oflag & ONOCR ? true : false; |
3479 onocr = t.c_oflag & ONOCR ? true : false; |
3484 onlret = t.c_oflag & ONLRET ? true : false; |
3480 onlret = t.c_oflag & ONLRET ? true : false; |
3485 |
3481 |
3486 sz = t.c_cflag & CSIZE; |
3482 sz = t.c_cflag & CSIZE; |
3487 switch (sz) { |
3483 switch (sz) { |
3488 case CS5: |
3484 case CS5: |
3489 csize = @symbol(cs5); |
3485 csize = @symbol(cs5); |
3490 break; |
3486 break; |
3491 case CS6: |
3487 case CS6: |
3492 csize = @symbol(cs6); |
3488 csize = @symbol(cs6); |
3493 break; |
3489 break; |
3494 case CS7: |
3490 case CS7: |
3495 csize = @symbol(cs7); |
3491 csize = @symbol(cs7); |
3496 break; |
3492 break; |
3497 case CS8: |
3493 case CS8: |
3498 csize = @symbol(cs8); |
3494 csize = @symbol(cs8); |
3499 break; |
3495 break; |
3500 } |
3496 } |
3501 cstopb = t.c_cflag & CSTOPB ? true : false; |
3497 cstopb = t.c_cflag & CSTOPB ? true : false; |
3502 cread = t.c_cflag & CREAD ? true : false; |
3498 cread = t.c_cflag & CREAD ? true : false; |
3503 parenb = t.c_cflag & PARENB ? true : false; |
3499 parenb = t.c_cflag & PARENB ? true : false; |
3504 parodd = t.c_cflag & PARODD ? true : false; |
3500 parodd = t.c_cflag & PARODD ? true : false; |
3530 #endif |
3526 #endif |
3531 |
3527 |
3532 out:; |
3528 out:; |
3533 %}. |
3529 %}. |
3534 error notNil ifTrue:[ |
3530 error notNil ifTrue:[ |
3535 error == #unsupportedOperation ifTrue:[ |
3531 error == #unsupportedOperation ifTrue:[ |
3536 "/ the system does not support tcgetattr |
3532 "/ the system does not support tcgetattr |
3537 ^ self errorUnsupportedOperation |
3533 ^ self errorUnsupportedOperation |
3538 ]. |
3534 ]. |
3539 lastErrorNumber := error. |
3535 lastErrorNumber := error. |
3540 ^ self ioError:error. |
3536 ^ self ioError:error. |
3541 ]. |
3537 ]. |
3542 handle isNil ifTrue:[^ self errorNotOpen]. |
3538 handle isNil ifTrue:[^ self errorNotOpen]. |
3543 |
3539 |
3544 "/ construct a dictionary... |
3540 "/ construct a dictionary... |
3545 ret := Dictionary new. |
3541 ret := Dictionary new. |
3599 |
3595 |
3600 |readCount| |
3596 |readCount| |
3601 |
3597 |
3602 readCount := self nextBytes:count into:aCollection startingAt:start. |
3598 readCount := self nextBytes:count into:aCollection startingAt:start. |
3603 readCount = count ifTrue:[ |
3599 readCount = count ifTrue:[ |
3604 ^ aCollection. |
3600 ^ aCollection. |
3605 ]. |
3601 ]. |
3606 ^ aCollection copyFrom:1 to:start+readCount-1. |
3602 ^ aCollection copyFrom:1 to:start+readCount-1. |
3607 ! |
3603 ! |
3608 |
3604 |
3609 nextAvailable:count |
3605 nextAvailable:count |
3615 |buffer n| |
3611 |buffer n| |
3616 |
3612 |
3617 buffer := self contentsSpecies uninitializedNew:count. |
3613 buffer := self contentsSpecies uninitializedNew:count. |
3618 n := self nextAvailableBytes:count into:buffer startingAt:1. |
3614 n := self nextAvailableBytes:count into:buffer startingAt:1. |
3619 n == 0 ifTrue:[ |
3615 n == 0 ifTrue:[ |
3620 binary ifTrue:[ |
3616 binary ifTrue:[ |
3621 ^ #[] |
3617 ^ #[] |
3622 ]. |
3618 ]. |
3623 ^ '' |
3619 ^ '' |
3624 ]. |
3620 ]. |
3625 |
3621 |
3626 n ~~ count ifTrue:[ |
3622 n ~~ count ifTrue:[ |
3627 ^ buffer copyTo:n |
3623 ^ buffer copyTo:n |
3628 ]. |
3624 ]. |
3629 ^ buffer. |
3625 ^ buffer. |
3630 |
3626 |
3631 " |
3627 " |
3632 (ReadStream on:#(1 2 3 4 5)) nextAvailable:3 |
3628 (ReadStream on:#(1 2 3 4 5)) nextAvailable:3 |
3680 if ((__INST(handleType) == nil) |
3676 if ((__INST(handleType) == nil) |
3681 || (__INST(handleType) == @symbol(filePointer)) |
3677 || (__INST(handleType) == @symbol(filePointer)) |
3682 || (__INST(handleType) == @symbol(socketFilePointer)) |
3678 || (__INST(handleType) == @symbol(socketFilePointer)) |
3683 || (__INST(handleType) == @symbol(socketHandle)) |
3679 || (__INST(handleType) == @symbol(socketHandle)) |
3684 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3680 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3685 if (((fp = __INST(handle)) != nil) |
3681 if (((fp = __INST(handle)) != nil) |
3686 && (__INST(mode) != @symbol(writeonly)) |
3682 && (__INST(mode) != @symbol(writeonly)) |
3687 && __bothSmallInteger(count, start) |
3683 && __bothSmallInteger(count, start) |
3688 ) { |
3684 ) { |
3689 f = __FILEVal(fp); |
3685 f = __FILEVal(fp); |
3690 |
3686 |
3691 cnt = __intVal(count); |
3687 cnt = __intVal(count); |
3692 offs = __intVal(start) - 1; |
3688 offs = __intVal(start) - 1; |
3693 |
3689 |
3694 if (__isExternalBytesLike(anObject)) { |
3690 if (__isExternalBytesLike(anObject)) { |
3695 OBJ sz; |
3691 OBJ sz; |
3696 |
3692 |
3697 nInstBytes = 0; |
3693 nInstBytes = 0; |
3698 extPtr = (char *)(__externalBytesAddress(anObject)); |
3694 extPtr = (char *)(__externalBytesAddress(anObject)); |
3699 if (extPtr == NULL) goto bad; |
3695 if (extPtr == NULL) goto bad; |
3700 sz = __externalBytesSize(anObject); |
3696 sz = __externalBytesSize(anObject); |
3701 if (__isSmallInteger(sz)) { |
3697 if (__isSmallInteger(sz)) { |
3702 objSize = __intVal(sz); |
3698 objSize = __intVal(sz); |
3703 } else { |
3699 } else { |
3704 objSize = 0; /* unknown */ |
3700 objSize = 0; /* unknown */ |
3705 } |
3701 } |
3706 } else { |
3702 } else { |
3707 OBJ oClass = __Class(anObject); |
3703 OBJ oClass = __Class(anObject); |
3708 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
3704 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
3709 |
3705 |
3710 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
3706 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
3711 |
3707 |
3712 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
3708 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
3713 case BYTEARRAY: |
3709 case BYTEARRAY: |
3714 case WORDARRAY: |
3710 case WORDARRAY: |
3715 case LONGARRAY: |
3711 case LONGARRAY: |
3716 case SWORDARRAY: |
3712 case SWORDARRAY: |
3717 case SLONGARRAY: |
3713 case SLONGARRAY: |
3718 case FLOATARRAY: |
3714 case FLOATARRAY: |
3719 break; |
3715 break; |
3720 case DOUBLEARRAY: |
3716 case DOUBLEARRAY: |
3721 #ifdef __NEED_DOUBLE_ALIGN |
3717 #ifdef __NEED_DOUBLE_ALIGN |
3722 nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1); |
3718 nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1); |
3723 #endif |
3719 #endif |
3724 break; |
3720 break; |
3725 case LONGLONGARRAY: |
3721 case LONGLONGARRAY: |
3726 case SLONGLONGARRAY: |
3722 case SLONGLONGARRAY: |
3727 #ifdef __NEED_LONGLONG_ALIGN |
3723 #ifdef __NEED_LONGLONG_ALIGN |
3728 nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1); |
3724 nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1); |
3729 #endif |
3725 #endif |
3730 break; |
3726 break; |
3731 default: |
3727 default: |
3732 goto bad; |
3728 goto bad; |
3733 } |
3729 } |
3734 extPtr = (char *)0; |
3730 extPtr = (char *)0; |
3735 objSize = __Size(anObject) - nInstBytes; |
3731 objSize = __Size(anObject) - nInstBytes; |
3736 } |
3732 } |
3737 |
3733 |
3738 if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) { |
3734 if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) { |
3739 _buffered = (__INST(buffered) == true); |
3735 _buffered = (__INST(buffered) == true); |
3740 if (_buffered) { |
3736 if (_buffered) { |
3741 __READING__(f); |
3737 __READING__(f); |
3742 } |
3738 } |
3743 |
3739 |
3744 if (extPtr) { |
3740 if (extPtr) { |
3745 __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType)); |
3741 __READAVAILBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType)); |
3746 } else { |
3742 } else { |
3747 /* |
3743 /* |
3748 * on interrupt, anObject may be moved to another location. |
3744 * on interrupt, anObject may be moved to another location. |
3749 * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__, |
3745 * So we pass (char *)__InstPtr(anObject) + nInstBytes + offs to the macro __READ_BYTES__, |
3750 * to get a new address. |
3746 * to get a new address. |
3751 */ |
3747 */ |
3752 offs += nInstBytes; |
3748 offs += nInstBytes; |
3753 __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType)); |
3749 __READAVAILBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType)); |
3754 } |
3750 } |
3755 /* 0 is NOT an EOF condition here ... */ |
3751 /* 0 is NOT an EOF condition here ... */ |
3756 if (ret >= 0) { |
3752 if (ret >= 0) { |
3757 if (__isSmallInteger(__INST(position))) { |
3753 if (__isSmallInteger(__INST(position))) { |
3758 INT np = __intVal(__INST(position)) + ret; |
3754 INT np = __intVal(__INST(position)) + ret; |
3759 OBJ t; |
3755 OBJ t; |
3760 |
3756 |
3761 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
3757 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
3762 } else { |
3758 } else { |
3763 __INST(position) = nil; /* i.e. do not know */ |
3759 __INST(position) = nil; /* i.e. do not know */ |
3764 } |
3760 } |
3765 RETURN (__mkSmallInteger(ret)); |
3761 RETURN (__mkSmallInteger(ret)); |
3766 } |
3762 } |
3767 __INST(position) = nil; |
3763 __INST(position) = nil; |
3768 error = __mkSmallInteger(__threadErrno); |
3764 error = __mkSmallInteger(__threadErrno); |
3769 } |
3765 } |
3770 } |
3766 } |
3771 } |
3767 } |
3772 bad: ; |
3768 bad: ; |
3773 %}. |
3769 %}. |
3774 hitEOF ifTrue:[^ 0]. |
3770 hitEOF ifTrue:[^ 0]. |
3775 error notNil ifTrue:[ |
3771 error notNil ifTrue:[ |
3776 lastErrorNumber := error. |
3772 lastErrorNumber := error. |
3777 ^ self readError:error |
3773 ^ self readError:error |
3778 ]. |
3774 ]. |
3779 handle isNil ifTrue:[^ self errorNotOpen]. |
3775 handle isNil ifTrue:[^ self errorNotOpen]. |
3780 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
3776 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
3781 " |
3777 " |
3782 count not integer or arg not bit-like (String, ByteArray etc) |
3778 count not integer or arg not bit-like (String, ByteArray etc) |
3793 %{ |
3789 %{ |
3794 #ifdef __SCHTEAM__ |
3790 #ifdef __SCHTEAM__ |
3795 STObject handle = self.instVarAt(I_handle); |
3791 STObject handle = self.instVarAt(I_handle); |
3796 |
3792 |
3797 if (handle != STObject.Nil) { |
3793 if (handle != STObject.Nil) { |
3798 STObject next; |
3794 STObject next; |
3799 |
3795 |
3800 next = handle.nextByte(); |
3796 next = handle.nextByte(); |
3801 if (next != STObject.EOF) { |
3797 if (next != STObject.EOF) { |
3802 self.instVarAt_put(I_position, STObject.Nil); |
3798 self.instVarAt_put(I_position, STObject.Nil); |
3803 return __c__._RETURN( next ); |
3799 return __c__._RETURN( next ); |
3804 } |
3800 } |
3805 self.instVarAt_put(I_hitEOF, STObject.True); |
3801 self.instVarAt_put(I_hitEOF, STObject.True); |
3806 } |
3802 } |
3807 #else |
3803 #else |
3808 FILEPOINTER f; |
3804 FILEPOINTER f; |
3809 unsigned char byte; |
3805 unsigned char byte; |
3810 int ret, _buffered; |
3806 int ret, _buffered; |
3814 if ((__INST(handleType) == nil) |
3810 if ((__INST(handleType) == nil) |
3815 || (__INST(handleType) == @symbol(filePointer)) |
3811 || (__INST(handleType) == @symbol(filePointer)) |
3816 || (__INST(handleType) == @symbol(socketFilePointer)) |
3812 || (__INST(handleType) == @symbol(socketFilePointer)) |
3817 || (__INST(handleType) == @symbol(socketHandle)) |
3813 || (__INST(handleType) == @symbol(socketHandle)) |
3818 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3814 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3819 if (((fp = __INST(handle)) != nil) |
3815 if (((fp = __INST(handle)) != nil) |
3820 && (__INST(mode) != @symbol(writeonly))) { |
3816 && (__INST(mode) != @symbol(writeonly))) { |
3821 f = __FILEVal(fp); |
3817 f = __FILEVal(fp); |
3822 |
3818 |
3823 _buffered = (__INST(buffered) == true); |
3819 _buffered = (__INST(buffered) == true); |
3824 if (_buffered) { |
3820 if (_buffered) { |
3825 __READING__(f) |
3821 __READING__(f) |
3826 } |
3822 } |
3827 __READBYTE__(ret, f, &byte, _buffered, __INST(handleType)); |
3823 __READBYTE__(ret, f, &byte, _buffered, __INST(handleType)); |
3828 if (ret > 0) { |
3824 if (ret > 0) { |
3829 if (__isSmallInteger(__INST(position))) { |
3825 if (__isSmallInteger(__INST(position))) { |
3830 INT np = __intVal(__INST(position)) + 1; |
3826 INT np = __intVal(__INST(position)) + 1; |
3831 OBJ t; |
3827 OBJ t; |
3832 |
3828 |
3833 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
3829 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
3834 } else { |
3830 } else { |
3835 __INST(position) = nil; /* i.e. do not know */ |
3831 __INST(position) = nil; /* i.e. do not know */ |
3836 } |
3832 } |
3837 RETURN (__mkSmallInteger(byte)); |
3833 RETURN (__mkSmallInteger(byte)); |
3838 } |
3834 } |
3839 |
3835 |
3840 if (ret == 0) { |
3836 if (ret == 0) { |
3841 __INST(hitEOF) = true; |
3837 __INST(hitEOF) = true; |
3842 } else /* ret < 0 */ { |
3838 } else /* ret < 0 */ { |
3843 __INST(position) = nil; |
3839 __INST(position) = nil; |
3844 error = __mkSmallInteger(__threadErrno); |
3840 error = __mkSmallInteger(__threadErrno); |
3845 } |
3841 } |
3846 } |
3842 } |
3847 } |
3843 } |
3848 #endif /* not SCHTEAM */ |
3844 #endif /* not SCHTEAM */ |
3849 %}. |
3845 %}. |
3850 hitEOF ifTrue:[^ self pastEndRead]. |
3846 hitEOF ifTrue:[^ self pastEndRead]. |
3851 error notNil ifTrue:[ |
3847 error notNil ifTrue:[ |
3852 lastErrorNumber := error. |
3848 lastErrorNumber := error. |
3853 ^ self readError:error |
3849 ^ self readError:error |
3854 ]. |
3850 ]. |
3855 handle isNil ifTrue:[^ self errorNotOpen]. |
3851 handle isNil ifTrue:[^ self errorNotOpen]. |
3856 ^ self errorWriteOnly |
3852 ^ self errorWriteOnly |
3857 ! |
3853 ! |
3858 |
3854 |
3893 if ((__INST(handleType) == nil) |
3889 if ((__INST(handleType) == nil) |
3894 || (__INST(handleType) == @symbol(filePointer)) |
3890 || (__INST(handleType) == @symbol(filePointer)) |
3895 || (__INST(handleType) == @symbol(socketFilePointer)) |
3891 || (__INST(handleType) == @symbol(socketFilePointer)) |
3896 || (__INST(handleType) == @symbol(socketHandle)) |
3892 || (__INST(handleType) == @symbol(socketHandle)) |
3897 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3893 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
3898 if (((fp = __INST(handle)) != nil) |
3894 if (((fp = __INST(handle)) != nil) |
3899 && (__INST(mode) != @symbol(writeonly)) |
3895 && (__INST(mode) != @symbol(writeonly)) |
3900 && __bothSmallInteger(count, start) |
3896 && __bothSmallInteger(count, start) |
3901 ) { |
3897 ) { |
3902 f = __FILEVal(fp); |
3898 f = __FILEVal(fp); |
3903 |
3899 |
3904 cnt = __intVal(count); |
3900 cnt = __intVal(count); |
3905 offs = __intVal(start) - 1; |
3901 offs = __intVal(start) - 1; |
3906 |
3902 |
3907 if (__isExternalBytesLike(anObject)) { |
3903 if (__isExternalBytesLike(anObject)) { |
3908 OBJ sz; |
3904 OBJ sz; |
3909 |
3905 |
3910 nInstBytes = 0; |
3906 nInstBytes = 0; |
3911 extPtr = (char *)(__externalBytesAddress(anObject)); |
3907 extPtr = (char *)(__externalBytesAddress(anObject)); |
3912 if (extPtr == NULL) goto bad; |
3908 if (extPtr == NULL) goto bad; |
3913 sz = __externalBytesSize(anObject); |
3909 sz = __externalBytesSize(anObject); |
3914 if (__isSmallInteger(sz)) { |
3910 if (__isSmallInteger(sz)) { |
3915 objSize = __intVal(sz); |
3911 objSize = __intVal(sz); |
3916 } else { |
3912 } else { |
3917 objSize = 0; /* unknown */ |
3913 objSize = 0; /* unknown */ |
3918 } |
3914 } |
3919 } else { |
3915 } else { |
3920 OBJ oClass = __Class(anObject); |
3916 OBJ oClass = __Class(anObject); |
3921 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
3917 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
3922 |
3918 |
3923 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
3919 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
3924 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
3920 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
3925 case BYTEARRAY: |
3921 case BYTEARRAY: |
3926 case WORDARRAY: |
3922 case WORDARRAY: |
3927 case LONGARRAY: |
3923 case LONGARRAY: |
3928 case SWORDARRAY: |
3924 case SWORDARRAY: |
3929 case SLONGARRAY: |
3925 case SLONGARRAY: |
3930 case FLOATARRAY: |
3926 case FLOATARRAY: |
3931 break; |
3927 break; |
3932 case DOUBLEARRAY: |
3928 case DOUBLEARRAY: |
3933 #ifdef __NEED_DOUBLE_ALIGN |
3929 #ifdef __NEED_DOUBLE_ALIGN |
3934 nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1); |
3930 nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1); |
3935 #endif |
3931 #endif |
3936 break; |
3932 break; |
3937 case LONGLONGARRAY: |
3933 case LONGLONGARRAY: |
3938 case SLONGLONGARRAY: |
3934 case SLONGLONGARRAY: |
3939 #ifdef __NEED_LONGLONG_ALIGN |
3935 #ifdef __NEED_LONGLONG_ALIGN |
3940 nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1); |
3936 nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1); |
3941 #endif |
3937 #endif |
3942 break; |
3938 break; |
3943 default: |
3939 default: |
3944 goto bad; |
3940 goto bad; |
3945 } |
3941 } |
3946 extPtr = (char *)0; |
3942 extPtr = (char *)0; |
3947 objSize = __Size(anObject) - nInstBytes; |
3943 objSize = __Size(anObject) - nInstBytes; |
3948 } |
3944 } |
3949 if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) { |
3945 if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) { |
3950 _buffered = (__INST(buffered) == true); |
3946 _buffered = (__INST(buffered) == true); |
3951 if (_buffered) { |
3947 if (_buffered) { |
3952 __READING__(f); |
3948 __READING__(f); |
3953 } |
3949 } |
3954 |
3950 |
3955 if (extPtr) { |
3951 if (extPtr) { |
3956 __READBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType)); |
3952 __READBYTES__(ret, f, extPtr+offs, cnt, _buffered, __INST(handleType)); |
3957 } else { |
3953 } else { |
3958 /* |
3954 /* |
3959 * on interrupt, anObject may be moved to another location. |
3955 * on interrupt, anObject may be moved to another location. |
3960 * So we pass anObject, and the offset to the __READBYTES_OBJ__ macro. |
3956 * So we pass anObject, and the offset to the __READBYTES_OBJ__ macro. |
3961 */ |
3957 */ |
3962 offs += nInstBytes; |
3958 offs += nInstBytes; |
3963 __READBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType)); |
3959 __READBYTES_OBJ__(ret, f, anObject, offs, cnt, _buffered, __INST(handleType)); |
3964 } |
3960 } |
3965 |
3961 |
3966 if (ret > 0) { |
3962 if (ret > 0) { |
3967 if (__isSmallInteger(__INST(position))) { |
3963 if (__isSmallInteger(__INST(position))) { |
3968 INT np = __intVal(__INST(position)) + ret; |
3964 INT np = __intVal(__INST(position)) + ret; |
3969 OBJ t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
3965 OBJ t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
3970 } else { |
3966 } else { |
3971 __INST(position) = nil; /* i.e. do not know */ |
3967 __INST(position) = nil; /* i.e. do not know */ |
3972 } |
3968 } |
3973 RETURN (__mkSmallInteger(ret)); |
3969 RETURN (__mkSmallInteger(ret)); |
3974 } |
3970 } |
3975 if (ret == 0) { |
3971 if (ret == 0) { |
3976 __INST(hitEOF) = true; |
3972 __INST(hitEOF) = true; |
3977 } else /* ret < 0 */ { |
3973 } else /* ret < 0 */ { |
3978 __INST(position) = nil; |
3974 __INST(position) = nil; |
3979 error = __mkSmallInteger(__threadErrno); |
3975 error = __mkSmallInteger(__threadErrno); |
3980 } |
3976 } |
3981 } |
3977 } |
3982 } |
3978 } |
3983 } |
3979 } |
3984 bad: ; |
3980 bad: ; |
3985 %}. |
3981 %}. |
3986 hitEOF ifTrue:[^ 0]. |
3982 hitEOF ifTrue:[^ 0]. |
3987 error notNil ifTrue:[ |
3983 error notNil ifTrue:[ |
3988 lastErrorNumber := error. |
3984 lastErrorNumber := error. |
3989 ^ self readError:error |
3985 ^ self readError:error |
3990 ]. |
3986 ]. |
3991 handle isNil ifTrue:[^ self errorNotOpen]. |
3987 handle isNil ifTrue:[^ self errorNotOpen]. |
3992 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
3988 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
3993 " |
3989 " |
3994 count not integer or arg not bit-like (String, ByteArray etc) |
3990 count not integer or arg not bit-like (String, ByteArray etc) |
4011 if ((__INST(handleType) == nil) |
4007 if ((__INST(handleType) == nil) |
4012 || (__INST(handleType) == @symbol(filePointer)) |
4008 || (__INST(handleType) == @symbol(filePointer)) |
4013 || (__INST(handleType) == @symbol(socketFilePointer)) |
4009 || (__INST(handleType) == @symbol(socketFilePointer)) |
4014 || (__INST(handleType) == @symbol(socketHandle)) |
4010 || (__INST(handleType) == @symbol(socketHandle)) |
4015 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4011 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4016 if (((fp = __INST(handle)) != nil) |
4012 if (((fp = __INST(handle)) != nil) |
4017 && (__INST(mode) != @symbol(writeonly)) |
4013 && (__INST(mode) != @symbol(writeonly)) |
4018 ) { |
4014 ) { |
4019 FILEPOINTER f; |
4015 FILEPOINTER f; |
4020 int ret, _buffered; |
4016 int ret, _buffered; |
4021 short value; |
4017 short value; |
4022 union { |
4018 union { |
4023 unsigned char buffer[2]; |
4019 unsigned char buffer[2]; |
4024 short shortVal; |
4020 short shortVal; |
4025 } u; |
4021 } u; |
4026 |
4022 |
4027 f = __FILEVal(fp); |
4023 f = __FILEVal(fp); |
4028 _buffered = (__INST(buffered) == true); |
4024 _buffered = (__INST(buffered) == true); |
4029 if (_buffered) { |
4025 if (_buffered) { |
4030 __READING__(f) |
4026 __READING__(f) |
4031 } |
4027 } |
4032 __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType)); |
4028 __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType)); |
4033 |
4029 |
4034 if (ret == 2) { |
4030 if (ret == 2) { |
4035 if (__isSmallInteger(__INST(position))) { |
4031 if (__isSmallInteger(__INST(position))) { |
4036 INT np = __intVal(__INST(position)) + 2; |
4032 INT np = __intVal(__INST(position)) + 2; |
4037 OBJ t; |
4033 OBJ t; |
4038 |
4034 |
4039 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4035 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4040 } else { |
4036 } else { |
4041 __INST(position) = nil; /* i.e. do not know */ |
4037 __INST(position) = nil; /* i.e. do not know */ |
4042 } |
4038 } |
4043 if (msbFlag == true) { |
4039 if (msbFlag == true) { |
4044 #if defined(__MSBFIRST__) |
4040 #if defined(__MSBFIRST__) |
4045 value = u.shortVal; |
4041 value = u.shortVal; |
4046 #else |
4042 #else |
4047 value = ((u.buffer[0] & 0xFF) << 8) | (u.buffer[1] & 0xFF); |
4043 value = ((u.buffer[0] & 0xFF) << 8) | (u.buffer[1] & 0xFF); |
4048 #endif |
4044 #endif |
4049 } else { |
4045 } else { |
4050 #if defined(__LSBFIRST__) |
4046 #if defined(__LSBFIRST__) |
4051 value = u.shortVal; |
4047 value = u.shortVal; |
4052 #else |
4048 #else |
4053 value = ((u.buffer[1] & 0xFF) << 8) | (u.buffer[0] & 0xFF); |
4049 value = ((u.buffer[1] & 0xFF) << 8) | (u.buffer[0] & 0xFF); |
4054 #endif |
4050 #endif |
4055 } |
4051 } |
4056 RETURN (__mkSmallInteger(value)); |
4052 RETURN (__mkSmallInteger(value)); |
4057 } |
4053 } |
4058 |
4054 |
4059 if (ret < 0) { |
4055 if (ret < 0) { |
4060 __INST(position) = nil; /* i.e. do not know */ |
4056 __INST(position) = nil; /* i.e. do not know */ |
4061 error = __mkSmallInteger(__threadErrno); |
4057 error = __mkSmallInteger(__threadErrno); |
4062 } else /* ret == 0 */ { |
4058 } else /* ret == 0 */ { |
4063 __INST(hitEOF) = true; |
4059 __INST(hitEOF) = true; |
4064 } |
4060 } |
4065 } |
4061 } |
4066 } |
4062 } |
4067 %}. |
4063 %}. |
4068 hitEOF ifTrue:[^ self pastEndRead]. |
4064 hitEOF ifTrue:[^ self pastEndRead]. |
4069 handle isNil ifTrue:[^ self errorNotOpen]. |
4065 handle isNil ifTrue:[^ self errorNotOpen]. |
4070 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4066 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4088 if ((__INST(handleType) == nil) |
4084 if ((__INST(handleType) == nil) |
4089 || (__INST(handleType) == @symbol(filePointer)) |
4085 || (__INST(handleType) == @symbol(filePointer)) |
4090 || (__INST(handleType) == @symbol(socketFilePointer)) |
4086 || (__INST(handleType) == @symbol(socketFilePointer)) |
4091 || (__INST(handleType) == @symbol(socketHandle)) |
4087 || (__INST(handleType) == @symbol(socketHandle)) |
4092 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4088 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4093 if (((fp = __INST(handle)) != nil) |
4089 if (((fp = __INST(handle)) != nil) |
4094 && (__INST(mode) != @symbol(writeonly)) |
4090 && (__INST(mode) != @symbol(writeonly)) |
4095 ) { |
4091 ) { |
4096 FILEPOINTER f; |
4092 FILEPOINTER f; |
4097 int ret, _buffered; |
4093 int ret, _buffered; |
4098 int value; |
4094 int value; |
4099 union { |
4095 union { |
4100 unsigned char buffer[4]; |
4096 unsigned char buffer[4]; |
4101 int intVal; |
4097 int intVal; |
4102 } u; |
4098 } u; |
4103 |
4099 |
4104 f = __FILEVal(fp); |
4100 f = __FILEVal(fp); |
4105 _buffered = (__INST(buffered) == true); |
4101 _buffered = (__INST(buffered) == true); |
4106 if (_buffered) { |
4102 if (_buffered) { |
4107 __READING__(f) |
4103 __READING__(f) |
4108 } |
4104 } |
4109 __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType)); |
4105 __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType)); |
4110 |
4106 |
4111 if (ret == 4) { |
4107 if (ret == 4) { |
4112 if (__isSmallInteger(__INST(position))) { |
4108 if (__isSmallInteger(__INST(position))) { |
4113 INT np = __intVal(__INST(position)) + 4; |
4109 INT np = __intVal(__INST(position)) + 4; |
4114 OBJ t; |
4110 OBJ t; |
4115 |
4111 |
4116 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4112 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4117 } else { |
4113 } else { |
4118 __INST(position) = nil; /* i.e. do not know */ |
4114 __INST(position) = nil; /* i.e. do not know */ |
4119 } |
4115 } |
4120 if (msbFlag == true) { |
4116 if (msbFlag == true) { |
4121 #if defined(__MSBFIRST__) |
4117 #if defined(__MSBFIRST__) |
4122 value = u.intVal; |
4118 value = u.intVal; |
4123 #else |
4119 #else |
4124 value = (u.buffer[0] & 0xFF); |
4120 value = (u.buffer[0] & 0xFF); |
4125 value = (value << 8) | (u.buffer[1] & 0xFF); |
4121 value = (value << 8) | (u.buffer[1] & 0xFF); |
4126 value = (value << 8) | (u.buffer[2] & 0xFF); |
4122 value = (value << 8) | (u.buffer[2] & 0xFF); |
4127 value = (value << 8) | (u.buffer[3] & 0xFF); |
4123 value = (value << 8) | (u.buffer[3] & 0xFF); |
4128 #endif |
4124 #endif |
4129 } else { |
4125 } else { |
4130 #if defined(__LSBFIRST__) |
4126 #if defined(__LSBFIRST__) |
4131 value = u.intVal; |
4127 value = u.intVal; |
4132 #else |
4128 #else |
4133 value = (u.buffer[3] & 0xFF); |
4129 value = (u.buffer[3] & 0xFF); |
4134 value = (value << 8) | (u.buffer[2] & 0xFF); |
4130 value = (value << 8) | (u.buffer[2] & 0xFF); |
4135 value = (value << 8) | (u.buffer[1] & 0xFF); |
4131 value = (value << 8) | (u.buffer[1] & 0xFF); |
4136 value = (value << 8) | (u.buffer[0] & 0xFF); |
4132 value = (value << 8) | (u.buffer[0] & 0xFF); |
4137 #endif |
4133 #endif |
4138 } |
4134 } |
4139 #if __POINTER_SIZE__ == 8 |
4135 #if __POINTER_SIZE__ == 8 |
4140 RETURN ( __mkSmallInteger(value)); |
4136 RETURN ( __mkSmallInteger(value)); |
4141 #else |
4137 #else |
4142 RETURN ( __MKINT(value) ); |
4138 RETURN ( __MKINT(value) ); |
4143 #endif |
4139 #endif |
4144 } |
4140 } |
4145 |
4141 |
4146 if (ret < 0) { |
4142 if (ret < 0) { |
4147 __INST(position) = nil; |
4143 __INST(position) = nil; |
4148 error = __mkSmallInteger(__threadErrno); |
4144 error = __mkSmallInteger(__threadErrno); |
4149 } else /* ret == 0 */ { |
4145 } else /* ret == 0 */ { |
4150 __INST(hitEOF) = true; |
4146 __INST(hitEOF) = true; |
4151 } |
4147 } |
4152 } |
4148 } |
4153 } |
4149 } |
4154 %}. |
4150 %}. |
4155 hitEOF ifTrue:[^ self pastEndRead]. |
4151 hitEOF ifTrue:[^ self pastEndRead]. |
4156 handle isNil ifTrue:[^ self errorNotOpen]. |
4152 handle isNil ifTrue:[^ self errorNotOpen]. |
4157 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4153 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4174 if ((__INST(handleType) == nil) |
4170 if ((__INST(handleType) == nil) |
4175 || (__INST(handleType) == @symbol(filePointer)) |
4171 || (__INST(handleType) == @symbol(filePointer)) |
4176 || (__INST(handleType) == @symbol(socketFilePointer)) |
4172 || (__INST(handleType) == @symbol(socketFilePointer)) |
4177 || (__INST(handleType) == @symbol(socketHandle)) |
4173 || (__INST(handleType) == @symbol(socketHandle)) |
4178 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4174 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4179 if (((fp = __INST(handle)) != nil) |
4175 if (((fp = __INST(handle)) != nil) |
4180 && (__INST(mode) != @symbol(writeonly)) |
4176 && (__INST(mode) != @symbol(writeonly)) |
4181 ) { |
4177 ) { |
4182 FILEPOINTER f; |
4178 FILEPOINTER f; |
4183 int ret, _buffered; |
4179 int ret, _buffered; |
4184 unsigned int value; |
4180 unsigned int value; |
4185 union { |
4181 union { |
4186 unsigned char buffer[2]; |
4182 unsigned char buffer[2]; |
4187 unsigned short shortVal; |
4183 unsigned short shortVal; |
4188 } u; |
4184 } u; |
4189 |
4185 |
4190 f = __FILEVal(fp); |
4186 f = __FILEVal(fp); |
4191 _buffered = (__INST(buffered) == true); |
4187 _buffered = (__INST(buffered) == true); |
4192 if (_buffered) { |
4188 if (_buffered) { |
4193 __READING__(f) |
4189 __READING__(f) |
4194 } |
4190 } |
4195 __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType)); |
4191 __READBYTES__(ret, f, u.buffer, 2, _buffered, __INST(handleType)); |
4196 |
4192 |
4197 if (ret == 2) { |
4193 if (ret == 2) { |
4198 if (__isSmallInteger(__INST(position))) { |
4194 if (__isSmallInteger(__INST(position))) { |
4199 INT np = __intVal(__INST(position)) + 2; |
4195 INT np = __intVal(__INST(position)) + 2; |
4200 OBJ t; |
4196 OBJ t; |
4201 |
4197 |
4202 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4198 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4203 } else { |
4199 } else { |
4204 __INST(position) = nil; /* i.e. do not know */ |
4200 __INST(position) = nil; /* i.e. do not know */ |
4205 } |
4201 } |
4206 if (msbFlag == true) { |
4202 if (msbFlag == true) { |
4207 #if defined(__MSBFIRST__) |
4203 #if defined(__MSBFIRST__) |
4208 value = u.shortVal; |
4204 value = u.shortVal; |
4209 #else |
4205 #else |
4210 value = (u.buffer[0] << 8) | u.buffer[1]; |
4206 value = (u.buffer[0] << 8) | u.buffer[1]; |
4211 #endif |
4207 #endif |
4212 } else { |
4208 } else { |
4213 #if defined(__LSBFIRST__) |
4209 #if defined(__LSBFIRST__) |
4214 value = u.shortVal; |
4210 value = u.shortVal; |
4215 #else |
4211 #else |
4216 value = (u.buffer[1] << 8) | u.buffer[0]; |
4212 value = (u.buffer[1] << 8) | u.buffer[0]; |
4217 #endif |
4213 #endif |
4218 } |
4214 } |
4219 RETURN (__mkSmallInteger(value)); |
4215 RETURN (__mkSmallInteger(value)); |
4220 } |
4216 } |
4221 |
4217 |
4222 if (ret < 0) { |
4218 if (ret < 0) { |
4223 __INST(position) = nil; /* i.e. do not know */ |
4219 __INST(position) = nil; /* i.e. do not know */ |
4224 error = __mkSmallInteger(__threadErrno); |
4220 error = __mkSmallInteger(__threadErrno); |
4225 } else /* ret == 0 */ { |
4221 } else /* ret == 0 */ { |
4226 __INST(hitEOF) = true; |
4222 __INST(hitEOF) = true; |
4227 } |
4223 } |
4228 } |
4224 } |
4229 } |
4225 } |
4230 %}. |
4226 %}. |
4231 hitEOF ifTrue:[^ self pastEndRead]. |
4227 hitEOF ifTrue:[^ self pastEndRead]. |
4232 handle isNil ifTrue:[^ self errorNotOpen]. |
4228 handle isNil ifTrue:[^ self errorNotOpen]. |
4233 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4229 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4251 if ((__INST(handleType) == nil) |
4247 if ((__INST(handleType) == nil) |
4252 || (__INST(handleType) == @symbol(filePointer)) |
4248 || (__INST(handleType) == @symbol(filePointer)) |
4253 || (__INST(handleType) == @symbol(socketFilePointer)) |
4249 || (__INST(handleType) == @symbol(socketFilePointer)) |
4254 || (__INST(handleType) == @symbol(socketHandle)) |
4250 || (__INST(handleType) == @symbol(socketHandle)) |
4255 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4251 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4256 if (((fp = __INST(handle)) != nil) |
4252 if (((fp = __INST(handle)) != nil) |
4257 && (__INST(mode) != @symbol(writeonly)) |
4253 && (__INST(mode) != @symbol(writeonly)) |
4258 ) { |
4254 ) { |
4259 FILEPOINTER f; |
4255 FILEPOINTER f; |
4260 int ret, _buffered; |
4256 int ret, _buffered; |
4261 unsigned INT value; |
4257 unsigned INT value; |
4262 union { |
4258 union { |
4263 unsigned char buffer[4]; |
4259 unsigned char buffer[4]; |
4264 unsigned int intVal; |
4260 unsigned int intVal; |
4265 } u; |
4261 } u; |
4266 |
4262 |
4267 f = __FILEVal(fp); |
4263 f = __FILEVal(fp); |
4268 _buffered = (__INST(buffered) == true); |
4264 _buffered = (__INST(buffered) == true); |
4269 if (_buffered) { |
4265 if (_buffered) { |
4270 __READING__(f) |
4266 __READING__(f) |
4271 } |
4267 } |
4272 __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType)); |
4268 __READBYTES__(ret, f, u.buffer, 4, _buffered, __INST(handleType)); |
4273 |
4269 |
4274 if (ret == 4) { |
4270 if (ret == 4) { |
4275 if (__isSmallInteger(__INST(position))) { |
4271 if (__isSmallInteger(__INST(position))) { |
4276 INT np = __intVal(__INST(position)) + 4; |
4272 INT np = __intVal(__INST(position)) + 4; |
4277 OBJ t; |
4273 OBJ t; |
4278 |
4274 |
4279 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4275 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4280 } else { |
4276 } else { |
4281 __INST(position) = nil; /* i.e. do not know */ |
4277 __INST(position) = nil; /* i.e. do not know */ |
4282 } |
4278 } |
4283 if (msbFlag == true) { |
4279 if (msbFlag == true) { |
4284 #if defined(__MSBFIRST__) |
4280 #if defined(__MSBFIRST__) |
4285 value = u.intVal; |
4281 value = u.intVal; |
4286 #else |
4282 #else |
4287 value = u.buffer[0]; |
4283 value = u.buffer[0]; |
4288 value = (value << 8) | u.buffer[1]; |
4284 value = (value << 8) | u.buffer[1]; |
4289 value = (value << 8) | u.buffer[2]; |
4285 value = (value << 8) | u.buffer[2]; |
4290 value = (value << 8) | u.buffer[3]; |
4286 value = (value << 8) | u.buffer[3]; |
4291 #endif |
4287 #endif |
4292 } else { |
4288 } else { |
4293 #if defined(__LSBFIRST__) |
4289 #if defined(__LSBFIRST__) |
4294 value = u.intVal; |
4290 value = u.intVal; |
4295 #else |
4291 #else |
4296 value = u.buffer[3]; |
4292 value = u.buffer[3]; |
4297 value = (value << 8) | u.buffer[2]; |
4293 value = (value << 8) | u.buffer[2]; |
4298 value = (value << 8) | u.buffer[1]; |
4294 value = (value << 8) | u.buffer[1]; |
4299 value = (value << 8) | u.buffer[0]; |
4295 value = (value << 8) | u.buffer[0]; |
4300 #endif |
4296 #endif |
4301 } |
4297 } |
4302 #if __POINTER_SIZE__ == 8 |
4298 #if __POINTER_SIZE__ == 8 |
4303 value &= 0xFFFFFFFF; |
4299 value &= 0xFFFFFFFF; |
4304 RETURN (__mkSmallInteger(value)); |
4300 RETURN (__mkSmallInteger(value)); |
4305 #else |
4301 #else |
4306 if (value <= _MAX_INT) { |
4302 if (value <= _MAX_INT) { |
4307 RETURN (__mkSmallInteger(value)); |
4303 RETURN (__mkSmallInteger(value)); |
4308 } |
4304 } |
4309 RETURN (__MKULARGEINT(value) ); |
4305 RETURN (__MKULARGEINT(value) ); |
4310 #endif |
4306 #endif |
4311 } |
4307 } |
4312 |
4308 |
4313 if (ret < 0) { |
4309 if (ret < 0) { |
4314 __INST(position) = nil; /* i.e. do not know */ |
4310 __INST(position) = nil; /* i.e. do not know */ |
4315 error = __mkSmallInteger(__threadErrno); |
4311 error = __mkSmallInteger(__threadErrno); |
4316 } else /* ret == 0 */ { |
4312 } else /* ret == 0 */ { |
4317 __INST(hitEOF) = true; |
4313 __INST(hitEOF) = true; |
4318 } |
4314 } |
4319 } |
4315 } |
4320 } |
4316 } |
4321 %}. |
4317 %}. |
4322 hitEOF ifTrue:[^ self pastEndRead]. |
4318 hitEOF ifTrue:[^ self pastEndRead]. |
4323 handle isNil ifTrue:[^ self errorNotOpen]. |
4319 handle isNil ifTrue:[^ self errorNotOpen]. |
4324 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4320 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
4327 ! |
4323 ! |
4328 |
4324 |
4329 nextWord |
4325 nextWord |
4330 <resource: #obsolete> |
4326 <resource: #obsolete> |
4331 "in text-mode: |
4327 "in text-mode: |
4332 read the alphaNumeric next word (i.e. up to non letter-or-digit). |
4328 read the alphaNumeric next word (i.e. up to non letter-or-digit). |
4333 return a string containing those characters. |
4329 return a string containing those characters. |
4334 in binary-mode: |
4330 in binary-mode: |
4335 read two bytes (msb-first) and return the value as a 16-bit |
4331 read two bytes (msb-first) and return the value as a 16-bit |
4336 unsigned Integer (for compatibility with other smalltalks)" |
4332 unsigned Integer (for compatibility with other smalltalks)" |
4337 |
4333 |
4338 binary ifTrue:[ |
4334 binary ifTrue:[ |
4339 self obsoleteMethodWarning:'use #nextUnsignedInt16MSB:true'. |
4335 self obsoleteMethodWarning:'use #nextUnsignedInt16MSB:true'. |
4340 ^ self nextUnsignedInt16MSB:true |
4336 ^ self nextUnsignedInt16MSB:true |
4341 ]. |
4337 ]. |
4342 self obsoleteMethodWarning:'use #nextAlphaNumericWord'. |
4338 self obsoleteMethodWarning:'use #nextAlphaNumericWord'. |
4343 ^ self nextAlphaNumericWord |
4339 ^ self nextAlphaNumericWord |
4344 ! ! |
4340 ! ! |
4345 |
4341 |
4358 if ((__INST(handleType) == nil) |
4354 if ((__INST(handleType) == nil) |
4359 || (__INST(handleType) == @symbol(filePointer)) |
4355 || (__INST(handleType) == @symbol(filePointer)) |
4360 || (__INST(handleType) == @symbol(socketFilePointer)) |
4356 || (__INST(handleType) == @symbol(socketFilePointer)) |
4361 || (__INST(handleType) == @symbol(socketHandle)) |
4357 || (__INST(handleType) == @symbol(socketHandle)) |
4362 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4358 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4363 if (((fp = __INST(handle)) != nil) |
4359 if (((fp = __INST(handle)) != nil) |
4364 && (__INST(mode) != @symbol(readonly)) |
4360 && (__INST(mode) != @symbol(readonly)) |
4365 && __isSmallInteger(aByteValue) |
4361 && __isSmallInteger(aByteValue) |
4366 |
4362 |
4367 ) { |
4363 ) { |
4368 int _buffered = (__INST(buffered) == true); |
4364 int _buffered = (__INST(buffered) == true); |
4369 FILEPOINTER f = __FILEVal(fp); |
4365 FILEPOINTER f = __FILEVal(fp); |
4370 char c = __intVal(aByteValue); |
4366 char c = __intVal(aByteValue); |
4371 int cnt; |
4367 int cnt; |
4372 |
4368 |
4373 if (_buffered) { |
4369 if (_buffered) { |
4374 __WRITING__(f) |
4370 __WRITING__(f) |
4375 } |
4371 } |
4376 #ifdef __win32__ |
4372 #ifdef __win32__ |
4377 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
4373 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
4378 cnt = __win32_fwrite(&c, 1, 1, f); |
4374 cnt = __win32_fwrite(&c, 1, 1, f); |
4379 } else |
4375 } else |
4380 #endif |
4376 #endif |
4381 { |
4377 { |
4382 __WRITEBYTE__(cnt, f, &c, _buffered, __INST(handleType)); |
4378 __WRITEBYTE__(cnt, f, &c, _buffered, __INST(handleType)); |
4383 } |
4379 } |
4384 if (cnt == 1) { |
4380 if (cnt == 1) { |
4385 if (__isSmallInteger(__INST(position))) { |
4381 if (__isSmallInteger(__INST(position))) { |
4386 INT np = __intVal(__INST(position)) + 1; |
4382 INT np = __intVal(__INST(position)) + 1; |
4387 OBJ t; |
4383 OBJ t; |
4388 |
4384 |
4389 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4385 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4390 } else { |
4386 } else { |
4391 __INST(position) = nil; /* i.e. do not know */ |
4387 __INST(position) = nil; /* i.e. do not know */ |
4392 } |
4388 } |
4393 RETURN (self); |
4389 RETURN (self); |
4394 } |
4390 } |
4395 if (cnt < 0) { |
4391 if (cnt < 0) { |
4396 __INST(position) = nil; /* i.e. do not know */ |
4392 __INST(position) = nil; /* i.e. do not know */ |
4397 } |
4393 } |
4398 error = __mkSmallInteger(__threadErrno); |
4394 error = __mkSmallInteger(__threadErrno); |
4399 } |
4395 } |
4400 } |
4396 } |
4401 %}. |
4397 %}. |
4402 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
4398 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
4403 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
4399 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
4404 lastErrorNumber := error. |
4400 lastErrorNumber := error. |
4415 |
4411 |
4416 |error| |
4412 |error| |
4417 %{ |
4413 %{ |
4418 int num; |
4414 int num; |
4419 union { |
4415 union { |
4420 char bytes[2]; |
4416 char bytes[2]; |
4421 short shortVal; |
4417 short shortVal; |
4422 } u; |
4418 } u; |
4423 OBJ fp; |
4419 OBJ fp; |
4424 |
4420 |
4425 __INST(lastErrorNumber) = nil; |
4421 __INST(lastErrorNumber) = nil; |
4426 if ((__INST(handleType) == nil) |
4422 if ((__INST(handleType) == nil) |
4427 || (__INST(handleType) == @symbol(filePointer)) |
4423 || (__INST(handleType) == @symbol(filePointer)) |
4428 || (__INST(handleType) == @symbol(socketFilePointer)) |
4424 || (__INST(handleType) == @symbol(socketFilePointer)) |
4429 || (__INST(handleType) == @symbol(socketHandle)) |
4425 || (__INST(handleType) == @symbol(socketHandle)) |
4430 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4426 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4431 if (((fp = __INST(handle)) != nil) |
4427 if (((fp = __INST(handle)) != nil) |
4432 && (__INST(mode) != @symbol(readonly)) |
4428 && (__INST(mode) != @symbol(readonly)) |
4433 ) { |
4429 ) { |
4434 FILEPOINTER f = __FILEVal(fp); |
4430 FILEPOINTER f = __FILEVal(fp); |
4435 int _buffered = (__INST(buffered) == true); |
4431 int _buffered = (__INST(buffered) == true); |
4436 int cnt; |
4432 int cnt; |
4437 |
4433 |
4438 if (__isSmallInteger(anIntegerOrCharacter)) { |
4434 if (__isSmallInteger(anIntegerOrCharacter)) { |
4439 num = __intVal(anIntegerOrCharacter); |
4435 num = __intVal(anIntegerOrCharacter); |
4440 } else if (__isCharacter(anIntegerOrCharacter)) { |
4436 } else if (__isCharacter(anIntegerOrCharacter)) { |
4441 num = __smallIntegerVal(__characterVal(anIntegerOrCharacter)); |
4437 num = __smallIntegerVal(__characterVal(anIntegerOrCharacter)); |
4442 } else |
4438 } else |
4443 goto out; |
4439 goto out; |
4444 |
4440 |
4445 if (msbFlag == true) { |
4441 if (msbFlag == true) { |
4446 #if defined(__MSBFIRST__) |
4442 #if defined(__MSBFIRST__) |
4447 u.shortVal = num; |
4443 u.shortVal = num; |
4448 #else |
4444 #else |
4449 u.bytes[0] = (num >> 8) & 0xFF; |
4445 u.bytes[0] = (num >> 8) & 0xFF; |
4450 u.bytes[1] = num & 0xFF; |
4446 u.bytes[1] = num & 0xFF; |
4451 #endif |
4447 #endif |
4452 } else { |
4448 } else { |
4453 #if defined(__LSBFIRST__) |
4449 #if defined(__LSBFIRST__) |
4454 u.shortVal = num; |
4450 u.shortVal = num; |
4455 #else |
4451 #else |
4456 u.bytes[1] = (num >> 8) & 0xFF; |
4452 u.bytes[1] = (num >> 8) & 0xFF; |
4457 u.bytes[0] = num & 0xFF; |
4453 u.bytes[0] = num & 0xFF; |
4458 #endif |
4454 #endif |
4459 } |
4455 } |
4460 |
4456 |
4461 if (_buffered) { |
4457 if (_buffered) { |
4462 __WRITING__(f) |
4458 __WRITING__(f) |
4463 } |
4459 } |
4464 __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType)); |
4460 __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType)); |
4465 |
4461 |
4466 if (cnt == 2) { |
4462 if (cnt == 2) { |
4467 if (__isSmallInteger(__INST(position))) { |
4463 if (__isSmallInteger(__INST(position))) { |
4468 INT np = __intVal(__INST(position)) + 2; |
4464 INT np = __intVal(__INST(position)) + 2; |
4469 OBJ t; |
4465 OBJ t; |
4470 |
4466 |
4471 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4467 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4472 } else { |
4468 } else { |
4473 __INST(position) = nil; /* i.e. do not know */ |
4469 __INST(position) = nil; /* i.e. do not know */ |
4474 } |
4470 } |
4475 RETURN ( self ); |
4471 RETURN ( self ); |
4476 } |
4472 } |
4477 __INST(position) = nil; /* i.e. do not know */ |
4473 __INST(position) = nil; /* i.e. do not know */ |
4478 error = __mkSmallInteger(__threadErrno); |
4474 error = __mkSmallInteger(__threadErrno); |
4479 } |
4475 } |
4480 } |
4476 } |
4481 out:; |
4477 out:; |
4482 %}. |
4478 %}. |
4483 error notNil ifTrue:[ |
4479 error notNil ifTrue:[ |
4484 lastErrorNumber := error. |
4480 lastErrorNumber := error. |
4485 self writeError:error. |
4481 self writeError:error. |
4486 ^ self |
4482 ^ self |
4487 ]. |
4483 ]. |
4488 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
4484 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
4489 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
4485 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
4490 self argumentMustBeInteger |
4486 self argumentMustBeInteger |
4491 |
4487 |
4515 |
4511 |
4516 |error| |
4512 |error| |
4517 %{ |
4513 %{ |
4518 int num; |
4514 int num; |
4519 union { |
4515 union { |
4520 char bytes[2]; |
4516 char bytes[2]; |
4521 short shortVal; |
4517 short shortVal; |
4522 } u; |
4518 } u; |
4523 OBJ fp; |
4519 OBJ fp; |
4524 |
4520 |
4525 __INST(lastErrorNumber) = nil; |
4521 __INST(lastErrorNumber) = nil; |
4526 if ((__INST(handleType) == nil) |
4522 if ((__INST(handleType) == nil) |
4527 || (__INST(handleType) == @symbol(filePointer)) |
4523 || (__INST(handleType) == @symbol(filePointer)) |
4528 || (__INST(handleType) == @symbol(socketFilePointer)) |
4524 || (__INST(handleType) == @symbol(socketFilePointer)) |
4529 || (__INST(handleType) == @symbol(socketHandle)) |
4525 || (__INST(handleType) == @symbol(socketHandle)) |
4530 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4526 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4531 if (((fp = __INST(handle)) != nil) |
4527 if (((fp = __INST(handle)) != nil) |
4532 && (__INST(mode) != @symbol(readonly)) |
4528 && (__INST(mode) != @symbol(readonly)) |
4533 ) { |
4529 ) { |
4534 FILEPOINTER f = __FILEVal(fp); |
4530 FILEPOINTER f = __FILEVal(fp); |
4535 int _buffered = (__INST(buffered) == true); |
4531 int _buffered = (__INST(buffered) == true); |
4536 int cnt; |
4532 int cnt; |
4537 |
4533 |
4538 if (__isSmallInteger(anIntegerOrCharacter)) { |
4534 if (__isSmallInteger(anIntegerOrCharacter)) { |
4539 num = __intVal(anIntegerOrCharacter); |
4535 num = __intVal(anIntegerOrCharacter); |
4540 } else if (__isCharacter(anIntegerOrCharacter)) { |
4536 } else if (__isCharacter(anIntegerOrCharacter)) { |
4541 num = __smallIntegerVal(__characterVal(anIntegerOrCharacter)); |
4537 num = __smallIntegerVal(__characterVal(anIntegerOrCharacter)); |
4542 } else |
4538 } else |
4543 goto out; |
4539 goto out; |
4544 |
4540 |
4545 u.shortVal = num; |
4541 u.shortVal = num; |
4546 |
4542 |
4547 if (_buffered) { |
4543 if (_buffered) { |
4548 __WRITING__(f) |
4544 __WRITING__(f) |
4549 } |
4545 } |
4550 __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType)); |
4546 __WRITEBYTES__(cnt, f, u.bytes, 2, _buffered, __INST(handleType)); |
4551 |
4547 |
4552 if (cnt == 2) { |
4548 if (cnt == 2) { |
4553 if (__isSmallInteger(__INST(position))) { |
4549 if (__isSmallInteger(__INST(position))) { |
4554 INT np = __intVal(__INST(position)) + 2; |
4550 INT np = __intVal(__INST(position)) + 2; |
4555 OBJ t; |
4551 OBJ t; |
4556 |
4552 |
4557 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4553 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4558 } else { |
4554 } else { |
4559 __INST(position) = nil; /* i.e. do not know */ |
4555 __INST(position) = nil; /* i.e. do not know */ |
4560 } |
4556 } |
4561 RETURN ( self ); |
4557 RETURN ( self ); |
4562 } |
4558 } |
4563 __INST(position) = nil; /* i.e. do not know */ |
4559 __INST(position) = nil; /* i.e. do not know */ |
4564 error = __mkSmallInteger(__threadErrno); |
4560 error = __mkSmallInteger(__threadErrno); |
4565 } |
4561 } |
4566 } |
4562 } |
4567 out:; |
4563 out:; |
4568 %}. |
4564 %}. |
4569 self nextPutInt16:anIntegerOrCharacter MSB:(UninterpretedBytes isBigEndian). |
4565 self nextPutInt16:anIntegerOrCharacter MSB:(UninterpretedBytes isBigEndian). |
4570 |
4566 |
4582 |error| |
4578 |error| |
4583 |
4579 |
4584 %{ |
4580 %{ |
4585 int num; |
4581 int num; |
4586 union { |
4582 union { |
4587 char bytes[4]; |
4583 char bytes[4]; |
4588 int intVal; |
4584 int intVal; |
4589 } u; |
4585 } u; |
4590 OBJ fp; |
4586 OBJ fp; |
4591 |
4587 |
4592 __INST(lastErrorNumber) = nil; |
4588 __INST(lastErrorNumber) = nil; |
4593 if (__isSmallInteger(aNumber)) { |
4589 if (__isSmallInteger(aNumber)) { |
4594 num = __intVal(aNumber); |
4590 num = __intVal(aNumber); |
4595 } else { |
4591 } else { |
4596 #if __POINTER_SIZE__ == 8 |
4592 #if __POINTER_SIZE__ == 8 |
4597 // always more than 4-bytes |
4593 // always more than 4-bytes |
4598 goto badArg; |
4594 goto badArg; |
4599 #else |
4595 #else |
4600 num = __longIntVal(aNumber); |
4596 num = __longIntVal(aNumber); |
4601 if (num == 0) { |
4597 if (num == 0) { |
4602 num = __signedLongIntVal(aNumber); |
4598 num = __signedLongIntVal(aNumber); |
4603 if (num == 0) { |
4599 if (num == 0) { |
4604 /* bad arg or out-of-range integer |
4600 /* bad arg or out-of-range integer |
4605 * (handled by the fallBack code) |
4601 * (handled by the fallBack code) |
4606 */ |
4602 */ |
4607 goto badArg; |
4603 goto badArg; |
4608 } |
4604 } |
4609 } |
4605 } |
4610 #endif |
4606 #endif |
4611 } |
4607 } |
4612 |
4608 |
4613 if ((__INST(handleType) == nil) |
4609 if ((__INST(handleType) == nil) |
4614 || (__INST(handleType) == @symbol(filePointer)) |
4610 || (__INST(handleType) == @symbol(filePointer)) |
4615 || (__INST(handleType) == @symbol(socketFilePointer)) |
4611 || (__INST(handleType) == @symbol(socketFilePointer)) |
4616 || (__INST(handleType) == @symbol(socketHandle)) |
4612 || (__INST(handleType) == @symbol(socketHandle)) |
4617 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4613 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4618 if (((fp = __INST(handle)) != nil) |
4614 if (((fp = __INST(handle)) != nil) |
4619 && (__INST(mode) != @symbol(readonly)) |
4615 && (__INST(mode) != @symbol(readonly)) |
4620 ) { |
4616 ) { |
4621 int _buffered = (__INST(buffered) == true); |
4617 int _buffered = (__INST(buffered) == true); |
4622 FILEPOINTER f = __FILEVal(fp); |
4618 FILEPOINTER f = __FILEVal(fp); |
4623 int cnt; |
4619 int cnt; |
4624 |
4620 |
4625 if (msbFlag == true) { |
4621 if (msbFlag == true) { |
4626 #if defined(__MSBFIRST__) |
4622 #if defined(__MSBFIRST__) |
4627 u.intVal = num; |
4623 u.intVal = num; |
4628 #else |
4624 #else |
4629 u.bytes[0] = (num >> 24) & 0xFF; |
4625 u.bytes[0] = (num >> 24) & 0xFF; |
4630 u.bytes[1] = (num >> 16) & 0xFF; |
4626 u.bytes[1] = (num >> 16) & 0xFF; |
4631 u.bytes[2] = (num >> 8) & 0xFF; |
4627 u.bytes[2] = (num >> 8) & 0xFF; |
4632 u.bytes[3] = num & 0xFF; |
4628 u.bytes[3] = num & 0xFF; |
4633 #endif |
4629 #endif |
4634 } else { |
4630 } else { |
4635 #if defined(__LSBFIRST__) |
4631 #if defined(__LSBFIRST__) |
4636 u.intVal = num; |
4632 u.intVal = num; |
4637 #else |
4633 #else |
4638 u.bytes[3] = (num >> 24) & 0xFF; |
4634 u.bytes[3] = (num >> 24) & 0xFF; |
4639 u.bytes[2] = (num >> 16) & 0xFF; |
4635 u.bytes[2] = (num >> 16) & 0xFF; |
4640 u.bytes[1] = (num >> 8) & 0xFF; |
4636 u.bytes[1] = (num >> 8) & 0xFF; |
4641 u.bytes[0] = num & 0xFF; |
4637 u.bytes[0] = num & 0xFF; |
4642 #endif |
4638 #endif |
4643 } |
4639 } |
4644 |
4640 |
4645 if (_buffered) { |
4641 if (_buffered) { |
4646 __WRITING__(f) |
4642 __WRITING__(f) |
4647 } |
4643 } |
4648 __WRITEBYTES__(cnt, f, u.bytes, 4, _buffered, __INST(handleType)); |
4644 __WRITEBYTES__(cnt, f, u.bytes, 4, _buffered, __INST(handleType)); |
4649 |
4645 |
4650 if (cnt == 4) { |
4646 if (cnt == 4) { |
4651 if (__isSmallInteger(__INST(position))) { |
4647 if (__isSmallInteger(__INST(position))) { |
4652 INT np = __intVal(__INST(position)) + 4; |
4648 INT np = __intVal(__INST(position)) + 4; |
4653 OBJ t; |
4649 OBJ t; |
4654 |
4650 |
4655 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4651 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4656 } else { |
4652 } else { |
4657 __INST(position) = nil; /* i.e. do not know */ |
4653 __INST(position) = nil; /* i.e. do not know */ |
4658 } |
4654 } |
4659 RETURN ( self ); |
4655 RETURN ( self ); |
4660 } |
4656 } |
4661 __INST(position) = nil; /* i.e. do not know */ |
4657 __INST(position) = nil; /* i.e. do not know */ |
4662 error = __mkSmallInteger(__threadErrno); |
4658 error = __mkSmallInteger(__threadErrno); |
4663 } |
4659 } |
4664 } |
4660 } |
4665 badArg: ; |
4661 badArg: ; |
4666 %}. |
4662 %}. |
4667 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
4663 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
4668 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
4664 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
4669 error notNil ifTrue:[ |
4665 error notNil ifTrue:[ |
4670 lastErrorNumber := error. |
4666 lastErrorNumber := error. |
4671 self writeError:error. |
4667 self writeError:error. |
4672 ^ self |
4668 ^ self |
4673 ]. |
4669 ]. |
4674 |
4670 |
4675 aNumber isInteger ifTrue:[ |
4671 aNumber isInteger ifTrue:[ |
4676 ^ super nextPutInt32:aNumber MSB:msbFlag |
4672 ^ super nextPutInt32:aNumber MSB:msbFlag |
4677 ]. |
4673 ]. |
4678 self argumentMustBeInteger |
4674 self argumentMustBeInteger |
4679 |
4675 |
4680 "Modified: / 19-09-2017 / 16:32:50 / stefan" |
4676 "Modified: / 19-09-2017 / 16:32:50 / stefan" |
4681 ! |
4677 ! |
4699 This is the CPU-specific byte order (LSB on x86, MSB on sparc, VAX and possibly on ARM). |
4695 This is the CPU-specific byte order (LSB on x86, MSB on sparc, VAX and possibly on ARM). |
4700 Notice that integers in the range 16r-80000000 to +16rFFFFFFFF can be written |
4696 Notice that integers in the range 16r-80000000 to +16rFFFFFFFF can be written |
4701 (i.e. both signed and unsigned int32 values can be written. |
4697 (i.e. both signed and unsigned int32 values can be written. |
4702 Works in both binary and text modes. |
4698 Works in both binary and text modes. |
4703 Notice: this message should not be sent explicitly by ANY program. |
4699 Notice: this message should not be sent explicitly by ANY program. |
4704 the following implementation replaces the code of either nextPutInt32MSB or LSB |
4700 the following implementation replaces the code of either nextPutInt32MSB or LSB |
4705 dynamically (see #initialize on the class side)" |
4701 dynamically (see #initialize on the class side)" |
4706 |
4702 |
4707 |error| |
4703 |error| |
4708 |
4704 |
4709 %{ |
4705 %{ |
4710 int num; |
4706 int num; |
4711 union { |
4707 union { |
4712 char bytes[4]; |
4708 char bytes[4]; |
4713 int intVal; |
4709 int intVal; |
4714 } u; |
4710 } u; |
4715 OBJ fp; |
4711 OBJ fp; |
4716 |
4712 |
4717 __INST(lastErrorNumber) = nil; |
4713 __INST(lastErrorNumber) = nil; |
4718 if (__isSmallInteger(anInteger)) { |
4714 if (__isSmallInteger(anInteger)) { |
4719 num = __intVal(anInteger); |
4715 num = __intVal(anInteger); |
4720 } else { |
4716 } else { |
4721 #if __POINTER_SIZE__ == 8 |
4717 #if __POINTER_SIZE__ == 8 |
4722 // always more than 4-bytes |
4718 // always more than 4-bytes |
4723 goto badArg; |
4719 goto badArg; |
4724 #else |
4720 #else |
4725 num = __longIntVal(anInteger); |
4721 num = __longIntVal(anInteger); |
4726 if (num == 0) { |
4722 if (num == 0) { |
4727 num = __signedLongIntVal(anInteger); |
4723 num = __signedLongIntVal(anInteger); |
4728 if (num == 0) { |
4724 if (num == 0) { |
4729 /* bad arg or out-of-range integer |
4725 /* bad arg or out-of-range integer |
4730 * (handled by the fallBack code) |
4726 * (handled by the fallBack code) |
4731 */ |
4727 */ |
4732 goto badArg; |
4728 goto badArg; |
4733 } |
4729 } |
4734 } |
4730 } |
4735 #endif |
4731 #endif |
4736 } |
4732 } |
4737 |
4733 |
4738 if ((__INST(handleType) == nil) |
4734 if ((__INST(handleType) == nil) |
4739 || (__INST(handleType) == @symbol(filePointer)) |
4735 || (__INST(handleType) == @symbol(filePointer)) |
4740 || (__INST(handleType) == @symbol(socketFilePointer)) |
4736 || (__INST(handleType) == @symbol(socketFilePointer)) |
4741 || (__INST(handleType) == @symbol(socketHandle)) |
4737 || (__INST(handleType) == @symbol(socketHandle)) |
4742 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4738 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
4743 if (((fp = __INST(handle)) != nil) |
4739 if (((fp = __INST(handle)) != nil) |
4744 && (__INST(mode) != @symbol(readonly)) |
4740 && (__INST(mode) != @symbol(readonly)) |
4745 ) { |
4741 ) { |
4746 int _buffered = (__INST(buffered) == true); |
4742 int _buffered = (__INST(buffered) == true); |
4747 FILEPOINTER f = __FILEVal(fp); |
4743 FILEPOINTER f = __FILEVal(fp); |
4748 int cnt; |
4744 int cnt; |
4749 |
4745 |
4750 u.intVal = num; |
4746 u.intVal = num; |
4751 if (_buffered) { |
4747 if (_buffered) { |
4752 __WRITING__(f) |
4748 __WRITING__(f) |
4753 } |
4749 } |
4754 __WRITEBYTES__(cnt, f, u.bytes, 4, _buffered, __INST(handleType)); |
4750 __WRITEBYTES__(cnt, f, u.bytes, 4, _buffered, __INST(handleType)); |
4755 |
4751 |
4756 if (cnt == 4) { |
4752 if (cnt == 4) { |
4757 if (__isSmallInteger(__INST(position))) { |
4753 if (__isSmallInteger(__INST(position))) { |
4758 INT np = __intVal(__INST(position)) + 4; |
4754 INT np = __intVal(__INST(position)) + 4; |
4759 OBJ t; |
4755 OBJ t; |
4760 |
4756 |
4761 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4757 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
4762 } else { |
4758 } else { |
4763 __INST(position) = nil; /* i.e. do not know */ |
4759 __INST(position) = nil; /* i.e. do not know */ |
4764 } |
4760 } |
4765 RETURN ( self ); |
4761 RETURN ( self ); |
4766 } |
4762 } |
4767 __INST(position) = nil; /* i.e. do not know */ |
4763 __INST(position) = nil; /* i.e. do not know */ |
4768 error = __mkSmallInteger(__threadErrno); |
4764 error = __mkSmallInteger(__threadErrno); |
4769 } |
4765 } |
4770 } |
4766 } |
4771 badArg: ; |
4767 badArg: ; |
4772 %}. |
4768 %}. |
4773 self nextPutInt32:anInteger MSB:(UninterpretedBytes isBigEndian) |
4769 self nextPutInt32:anInteger MSB:(UninterpretedBytes isBigEndian) |
4774 |
4770 |
4780 UTF-16 can encode only characters with code points between 0 to 16r10FFFF." |
4776 UTF-16 can encode only characters with code points between 0 to 16r10FFFF." |
4781 |
4777 |
4782 self nextPutUtf16Bytes:aCharacter MSB:true |
4778 self nextPutUtf16Bytes:aCharacter MSB:true |
4783 |
4779 |
4784 " |
4780 " |
4785 (FileStream newTemporary |
4781 (FileStream newTemporary |
4786 nextPutUtf16:$B; |
4782 nextPutUtf16:$B; |
4787 nextPutUtf16:$Ă„; |
4783 nextPutUtf16:$Ă„; |
4788 nextPutUtf16:(Character codePoint:16r10CCCC); |
4784 nextPutUtf16:(Character codePoint:16r10CCCC); |
4789 reset; |
4785 reset; |
4790 binary; |
4786 binary; |
4791 contents) |
4787 contents) |
4792 " |
4788 " |
4793 ! |
4789 ! |
4794 |
4790 |
4795 nextPutUtf16:aCharacter MSB:msbFlag |
4791 nextPutUtf16:aCharacter MSB:msbFlag |
4796 "append my UTF-16 MSB representation to the argument, aStream. |
4792 "append my UTF-16 MSB representation to the argument, aStream. |
4811 |
4807 |
4812 !ExternalStream methodsFor:'printing & storing'! |
4808 !ExternalStream methodsFor:'printing & storing'! |
4813 |
4809 |
4814 printOn:aStream |
4810 printOn:aStream |
4815 aStream |
4811 aStream |
4816 nextPutAll:self className; |
4812 nextPutAll:self className; |
4817 nextPut:$(. |
4813 nextPut:$(. |
4818 handleType printOn:aStream. |
4814 handleType printOn:aStream. |
4819 aStream nextPutAll:':('. |
4815 aStream nextPutAll:':('. |
4820 handle printOn:aStream. |
4816 handle printOn:aStream. |
4821 aStream nextPutAll:'))' |
4817 aStream nextPutAll:'))' |
4822 ! ! |
4818 ! ! |
4832 Don't send this message, send #close instead" |
4828 Don't send this message, send #close instead" |
4833 |
4829 |
4834 |fp error| |
4830 |fp error| |
4835 |
4831 |
4836 handle isNil ifTrue:[ |
4832 handle isNil ifTrue:[ |
4837 ^ self. |
4833 ^ self. |
4838 ]. |
4834 ]. |
4839 fp := handle. |
4835 fp := handle. |
4840 "/ (didWrite==true and:[binary ~~ true and:[eolMode = #crlf]]) ifTrue: [ self breakPoint:#sr ]. |
4836 "/ (didWrite==true and:[binary ~~ true and:[eolMode = #crlf]]) ifTrue: [ self breakPoint:#sr ]. |
4841 |
4837 |
4842 %{ |
4838 %{ |
4843 int rslt; |
4839 int rslt; |
4844 |
4840 |
4845 if (__INST(handleType) == @symbol(socketHandle)) { |
4841 if (__INST(handleType) == @symbol(socketHandle)) { |
4846 SOCKET sock = (SOCKET)(__FILEVal(fp)); |
4842 SOCKET sock = (SOCKET)(__FILEVal(fp)); |
4847 |
4843 |
4848 if (@global(FileOpenTrace) == true) { |
4844 if (@global(FileOpenTrace) == true) { |
4849 fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", (INT)sock); |
4845 fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", (INT)sock); |
4850 } |
4846 } |
4851 |
4847 |
4852 // whether the close() will be successful or not - the handle is invalid now! |
4848 // whether the close() will be successful or not - the handle is invalid now! |
4853 __INST(handle) = nil; |
4849 __INST(handle) = nil; |
4854 do { |
4850 do { |
4855 #ifdef __win32__ |
4851 #ifdef __win32__ |
4856 rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock); |
4852 rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock); |
4857 #else |
4853 #else |
4858 rslt = close(sock); |
4854 rslt = close(sock); |
4859 #endif |
4855 #endif |
4860 } while((rslt < 0) && (__threadErrno == EINTR)); |
4856 } while((rslt < 0) && (__threadErrno == EINTR)); |
4861 } else if ((__INST(handleType) == nil) |
4857 } else if ((__INST(handleType) == nil) |
4862 || (__INST(handleType) == @symbol(filePointer)) |
4858 || (__INST(handleType) == @symbol(filePointer)) |
4863 || (__INST(handleType) == @symbol(socketFilePointer)) |
4859 || (__INST(handleType) == @symbol(socketFilePointer)) |
4864 || (__INST(handleType) == @symbol(pipeFilePointer))) |
4860 || (__INST(handleType) == @symbol(pipeFilePointer))) |
4865 { |
4861 { |
4866 FILEPOINTER f = __FILEVal(fp); |
4862 FILEPOINTER f = __FILEVal(fp); |
4867 |
4863 |
4868 if (@global(FileOpenTrace) == true) { |
4864 if (@global(FileOpenTrace) == true) { |
4869 fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f); |
4865 fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f); |
4870 } |
4866 } |
4871 // whether the close() will be successful or not - the handle is invalid now! |
4867 // whether the close() will be successful or not - the handle is invalid now! |
4872 __INST(handle) = nil; |
4868 __INST(handle) = nil; |
4873 |
4869 |
4874 #ifdef __win32__ |
4870 #ifdef __win32__ |
4875 if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) { |
4871 if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) { |
4876 // do a fflush() first, so that fclose() doesn't block |
4872 // do a fflush() first, so that fclose() doesn't block |
4877 // we suspect, that EINTR causes problems in fclose() |
4873 // we suspect, that EINTR causes problems in fclose() |
4878 do { |
4874 do { |
4879 __threadErrno = 0; |
4875 __threadErrno = 0; |
4880 rslt = __STX_C_CALL1("fflush", fflush, f); |
4876 rslt = __STX_C_CALL1("fflush", fflush, f); |
4881 } while((rslt < 0) && (__threadErrno == EINTR)); |
4877 } while((rslt < 0) && (__threadErrno == EINTR)); |
4882 } |
4878 } |
4883 do { |
4879 do { |
4884 __threadErrno = 0; |
4880 __threadErrno = 0; |
4885 rslt = __STX_C_NOINT_CALL1("fclose", fclose, f); |
4881 rslt = __STX_C_NOINT_CALL1("fclose", fclose, f); |
4886 } while((rslt < 0) && (__threadErrno == EINTR)); |
4882 } while((rslt < 0) && (__threadErrno == EINTR)); |
4887 #else |
4883 #else |
4888 // cg: not sure why, but on osx, I get blocked occasionally in fclose |
4884 // cg: not sure why, but on osx, I get blocked occasionally in fclose |
4889 // lets try this: |
4885 // lets try this: |
4890 if ((__INST(mode) != @symbol(readonly)) && (__INST(buffered) != false)) { |
4886 if ((__INST(mode) != @symbol(readonly)) && (__INST(buffered) != false)) { |
4891 // do a fflush() first, so that fclose() doesn't block |
4887 // do a fflush() first, so that fclose() doesn't block |
4892 // we suspect, that EINTR causes problems in fclose() |
4888 // we suspect, that EINTR causes problems in fclose() |
4893 do { |
4889 do { |
4894 clearerr(f); |
4890 clearerr(f); |
4895 __threadErrno = 0; |
4891 __threadErrno = 0; |
4896 __BEGIN_INTERRUPTABLE__ |
4892 __BEGIN_INTERRUPTABLE__ |
4897 rslt = fflush(f); |
4893 rslt = fflush(f); |
4898 __END_INTERRUPTABLE__ |
4894 __END_INTERRUPTABLE__ |
4899 } while((rslt < 0) && (__threadErrno == EINTR)); |
4895 } while((rslt < 0) && (__threadErrno == EINTR)); |
4900 } |
4896 } |
4901 do { |
4897 do { |
4902 __threadErrno = 0; |
4898 __threadErrno = 0; |
4903 __BEGIN_INTERRUPTABLE__ |
4899 __BEGIN_INTERRUPTABLE__ |
4904 rslt = fclose(f); |
4900 rslt = fclose(f); |
4905 __END_INTERRUPTABLE__ |
4901 __END_INTERRUPTABLE__ |
4906 } while((rslt < 0) && (__threadErrno == EINTR)); |
4902 } while((rslt < 0) && (__threadErrno == EINTR)); |
4907 #endif |
4903 #endif |
4908 } else { |
4904 } else { |
4909 error = @symbol(badHandleType); |
4905 error = @symbol(badHandleType); |
4910 goto out; |
4906 goto out; |
4911 } |
4907 } |
4912 |
4908 |
4913 if (rslt < 0) { |
4909 if (rslt < 0) { |
4914 error = __mkSmallInteger(__threadErrno); |
4910 error = __mkSmallInteger(__threadErrno); |
4915 goto out; |
4911 goto out; |
4916 } |
4912 } |
4917 RETURN (self); |
4913 RETURN (self); |
4918 |
4914 |
4919 out:; |
4915 out:; |
4920 %}. |
4916 %}. |
4921 |
4917 |
4922 error notNil ifTrue:[ |
4918 error notNil ifTrue:[ |
4923 error isInteger ifTrue:[ |
4919 error isInteger ifTrue:[ |
4924 lastErrorNumber := error. |
4920 lastErrorNumber := error. |
4925 mode == #readonly ifTrue:[ |
4921 mode == #readonly ifTrue:[ |
4926 self ioError:error. |
4922 self ioError:error. |
4927 ] ifFalse:[ |
4923 ] ifFalse:[ |
4928 self writeError:error. |
4924 self writeError:error. |
4929 ]. |
4925 ]. |
4930 ^ self. |
4926 ^ self. |
4931 ]. |
4927 ]. |
4932 self primitiveFailed:error. |
4928 self primitiveFailed:error. |
4933 ^ self. |
4929 ^ self. |
4934 ]. |
4930 ]. |
4935 |
4931 |
4936 "/ fallback for rel5 |
4932 "/ fallback for rel5 |
4937 |
4933 |
4938 fp := handle. |
4934 fp := handle. |
4939 fp notNil ifTrue:[ |
4935 fp notNil ifTrue:[ |
4940 handle := nil. |
4936 handle := nil. |
4941 self closeFile:fp |
4937 self closeFile:fp |
4942 ] |
4938 ] |
4943 |
4939 |
4944 "Modified: / 19-04-2018 / 10:57:54 / stefan" |
4940 "Modified: / 19-04-2018 / 10:57:54 / stefan" |
4945 ! |
4941 ! |
4946 |
4942 |
4969 FILE *fdopen(); |
4965 FILE *fdopen(); |
4970 int fd = -2; |
4966 int fd = -2; |
4971 |
4967 |
4972 if (__isStringLike(openmode)) { |
4968 if (__isStringLike(openmode)) { |
4973 #ifdef __win32__ |
4969 #ifdef __win32__ |
4974 __stxWrapApiEnterCritical(); |
4970 __stxWrapApiEnterCritical(); |
4975 #endif |
4971 #endif |
4976 if (__isSmallInteger(aFileDescriptor)) { |
4972 if (__isSmallInteger(aFileDescriptor)) { |
4977 fd = __intVal(aFileDescriptor); |
4973 fd = __intVal(aFileDescriptor); |
4978 } |
4974 } |
4979 #ifdef __win32__ |
4975 #ifdef __win32__ |
4980 else if (__isExternalAddressLike(aFileDescriptor)) { |
4976 else if (__isExternalAddressLike(aFileDescriptor)) { |
4981 fd = _open_osfhandle((long)__externalAddressVal(aFileDescriptor), O_BINARY); |
4977 fd = _open_osfhandle((long)__externalAddressVal(aFileDescriptor), O_BINARY); |
4982 if (fd < 0) { |
4978 if (fd < 0) { |
4983 if (__threadErrno == 0) { |
4979 if (__threadErrno == 0) { |
4984 // no more file descriptors |
4980 // no more file descriptors |
4985 __threadErrno = EMFILE; |
4981 __threadErrno = EMFILE; |
4986 } |
4982 } |
4987 error = __mkSmallInteger(__threadErrno); |
4983 error = __mkSmallInteger(__threadErrno); |
4988 __stxWrapApiLeaveCritical(); |
4984 __stxWrapApiLeaveCritical(); |
4989 goto out; |
4985 goto out; |
4990 } |
4986 } |
4991 } |
4987 } |
4992 #endif |
4988 #endif |
4993 f = (FILEPOINTER) fdopen(fd, (char *)__stringVal(openmode)); |
4989 f = (FILEPOINTER) fdopen(fd, (char *)__stringVal(openmode)); |
4994 #ifdef __win32__ |
4990 #ifdef __win32__ |
4995 __stxWrapApiLeaveCritical(); |
4991 __stxWrapApiLeaveCritical(); |
4996 #endif |
4992 #endif |
4997 if (f == NULL) { |
4993 if (f == NULL) { |
4998 error =__mkSmallInteger(__threadErrno); |
4994 error =__mkSmallInteger(__threadErrno); |
4999 } else { |
4995 } else { |
5000 if (@global(FileOpenTrace) == true) { |
4996 if (@global(FileOpenTrace) == true) { |
5001 fprintf(stderr, "fdopen [ExternalStream] %"_ld_" (%"_lx_") -> %"_lx_"\n", (INT)fd, (INT)fd, (INT)f); |
4997 fprintf(stderr, "fdopen [ExternalStream] %"_ld_" (%"_lx_") -> %"_lx_"\n", (INT)fd, (INT)fd, (INT)f); |
5002 } |
4998 } |
5003 |
4999 |
5004 fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp); |
5000 fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp); |
5005 } |
5001 } |
5006 } |
5002 } |
5007 out:; |
5003 out:; |
5008 %}. |
5004 %}. |
5009 error notNil ifTrue:[ |
5005 error notNil ifTrue:[ |
5010 " |
5006 " |
5011 the open failed for some reason ... |
5007 the open failed for some reason ... |
5012 " |
5008 " |
5013 OperatingSystem closeFd:aFileDescriptor. |
5009 OperatingSystem closeFd:aFileDescriptor. |
5014 lastErrorNumber := error. |
5010 lastErrorNumber := error. |
5015 position := nil. |
5011 position := nil. |
5016 ^ self openError:error |
5012 ^ self openError:error |
5017 ]. |
5013 ]. |
5018 |
5014 |
5019 position := 0. |
5015 position := 0. |
5020 buffered isNil ifTrue:[ |
5016 buffered isNil ifTrue:[ |
5021 buffered := true. "default is buffered" |
5017 buffered := true. "default is buffered" |
5022 ]. |
5018 ]. |
5023 handleType := handleTypeSymbol. |
5019 handleType := handleTypeSymbol. |
5024 self registerForFinalization. |
5020 self registerForFinalization. |
5025 ! |
5021 ! |
5026 |
5022 |
5029 |
5025 |
5030 |fd dupFd| |
5026 |fd dupFd| |
5031 |
5027 |
5032 fd := self fileHandle. |
5028 fd := self fileHandle. |
5033 fd isNil ifTrue:[ |
5029 fd isNil ifTrue:[ |
5034 ^ self errorNotOpen. |
5030 ^ self errorNotOpen. |
5035 ]. |
5031 ]. |
5036 dupFd := OperatingSystem dup:fd. |
5032 dupFd := OperatingSystem dup:fd. |
5037 self setFileHandle:dupFd mode:self fopenMode. |
5033 self setFileHandle:dupFd mode:self fopenMode. |
5038 ! |
5034 ! |
5039 |
5035 |
5040 fopenMode |
5036 fopenMode |
5041 "answer the mode for fopen. |
5037 "answer the mode for fopen. |
5042 Only used internally" |
5038 Only used internally" |
5043 |
5039 |
5044 mode == #readonly ifTrue:[ |
5040 mode == #readonly ifTrue:[ |
5045 ^ ReadMode |
5041 ^ ReadMode |
5046 ]. |
5042 ]. |
5047 mode == #writeonly ifTrue:[ |
5043 mode == #writeonly ifTrue:[ |
5048 ^ WriteMode |
5044 ^ WriteMode |
5049 ]. |
5045 ]. |
5050 mode == #readWrite ifTrue:[ |
5046 mode == #readWrite ifTrue:[ |
5051 ^ ReadWriteMode |
5047 ^ ReadWriteMode |
5052 ]. |
5048 ]. |
5053 mode == #append ifTrue:[ |
5049 mode == #append ifTrue:[ |
5054 ^ AppendMode |
5050 ^ AppendMode |
5055 ]. |
5051 ]. |
5056 ^ ReadWriteMode |
5052 ^ ReadWriteMode |
5057 ! |
5053 ! |
5058 |
5054 |
5059 open:aPath withMode:openModeString |
5055 open:aPath withMode:openModeString |
5070 if (__isStringLike(aPath) && __isStringLike(openModeString)) { |
5066 if (__isStringLike(aPath) && __isStringLike(openModeString)) { |
5071 #ifdef __win32__ |
5067 #ifdef __win32__ |
5072 # if 1 |
5068 # if 1 |
5073 f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString)); |
5069 f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString)); |
5074 # else |
5070 # else |
5075 __BEGIN_INTERRUPTABLE__ |
5071 __BEGIN_INTERRUPTABLE__ |
5076 do { |
5072 do { |
5077 f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString)); |
5073 f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString)); |
5078 } while ((f == NULL) && (__threadErrno == EINTR)); |
5074 } while ((f == NULL) && (__threadErrno == EINTR)); |
5079 __END_INTERRUPTABLE__ |
5075 __END_INTERRUPTABLE__ |
5080 # endif |
5076 # endif |
5081 #else /* UNIX */ |
5077 #else /* UNIX */ |
5082 __BEGIN_INTERRUPTABLE__ |
5078 __BEGIN_INTERRUPTABLE__ |
5083 do { |
5079 do { |
5084 f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString)); |
5080 f = fopen((char *) __stringVal(aPath), (char *) __stringVal(openModeString)); |
5085 } while ((f == NULL) && (__threadErrno == EINTR)); |
5081 } while ((f == NULL) && (__threadErrno == EINTR)); |
5086 __END_INTERRUPTABLE__ |
5082 __END_INTERRUPTABLE__ |
5087 #endif /* UNIX */ |
5083 #endif /* UNIX */ |
5088 if (f == NULL) { |
5084 if (f == NULL) { |
5089 error = __mkSmallInteger(__threadErrno); |
5085 error = __mkSmallInteger(__threadErrno); |
5090 } else { |
5086 } else { |
5091 if (@global(FileOpenTrace) == true) { |
5087 if (@global(FileOpenTrace) == true) { |
5092 fprintf(stderr, "fopen %s [ExternalStream] -> %"_lx_"\n", __stringVal(aPath), (INT)f); |
5088 fprintf(stderr, "fopen %s [ExternalStream] -> %"_lx_"\n", __stringVal(aPath), (INT)f); |
5093 } |
5089 } |
5094 fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp); |
5090 fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp); |
5095 __INST(handleType) = @symbol(filePointer); |
5091 __INST(handleType) = @symbol(filePointer); |
5096 ok = true; |
5092 ok = true; |
5097 } |
5093 } |
5098 } |
5094 } |
5099 %}. |
5095 %}. |
5100 ok ifTrue:[ |
5096 ok ifTrue:[ |
5101 position := 0. |
5097 position := 0. |
5102 self registerForFinalization. |
5098 self registerForFinalization. |
5103 ^ self. |
5099 ^ self. |
5104 ]. |
5100 ]. |
5105 error notNil ifTrue:[ |
5101 error notNil ifTrue:[ |
5106 " |
5102 " |
5107 the open failed for some reason ... |
5103 the open failed for some reason ... |
5108 " |
5104 " |
5109 lastErrorNumber := error. |
5105 lastErrorNumber := error. |
5110 self openError:error. |
5106 self openError:error. |
5111 ]. |
5107 ]. |
5112 self primitiveFailed. |
5108 self primitiveFailed. |
5113 ! |
5109 ! |
5114 |
5110 |
5115 reOpen |
5111 reOpen |
5152 OBJ fp; |
5148 OBJ fp; |
5153 FILE *fdopen(); |
5149 FILE *fdopen(); |
5154 int fd; |
5150 int fd; |
5155 |
5151 |
5156 if (!__isStringLike(openMode)) |
5152 if (!__isStringLike(openMode)) |
5157 goto err; |
5153 goto err; |
5158 |
5154 |
5159 #ifdef __win32__ |
5155 #ifdef __win32__ |
5160 __stxWrapApiEnterCritical(); |
5156 __stxWrapApiEnterCritical(); |
5161 if (__isExternalAddressLike(anIntegerOrExternalAddress) ) { |
5157 if (__isExternalAddressLike(anIntegerOrExternalAddress) ) { |
5162 HANDLE __fileHandle = (HANDLE)__externalAddressVal(anIntegerOrExternalAddress); |
5158 HANDLE __fileHandle = (HANDLE)__externalAddressVal(anIntegerOrExternalAddress); |
5163 fd = _open_osfhandle((long)__fileHandle, O_BINARY); /* should we handle readonly, append or text mode? */ |
5159 fd = _open_osfhandle((long)__fileHandle, O_BINARY); /* should we handle readonly, append or text mode? */ |
5164 if (fd < 0) { |
5160 if (fd < 0) { |
5165 __stxWrapApiLeaveCritical(); |
5161 __stxWrapApiLeaveCritical(); |
5166 CloseHandle(__fileHandle); |
5162 CloseHandle(__fileHandle); |
5167 goto err; |
5163 goto err; |
5168 } |
5164 } |
5169 } else |
5165 } else |
5170 #endif |
5166 #endif |
5171 if (__isSmallInteger(anIntegerOrExternalAddress)) { |
5167 if (__isSmallInteger(anIntegerOrExternalAddress)) { |
5172 fd = __smallIntegerVal(anIntegerOrExternalAddress); |
5168 fd = __smallIntegerVal(anIntegerOrExternalAddress); |
5173 } else { |
5169 } else { |
5174 #ifdef __win32__ |
5170 #ifdef __win32__ |
5175 __stxWrapApiLeaveCritical(); |
5171 __stxWrapApiLeaveCritical(); |
5176 #endif |
5172 #endif |
5177 goto err; |
5173 goto err; |
5178 } |
5174 } |
5179 f = fdopen(fd, __stringVal(openMode)); |
5175 f = fdopen(fd, __stringVal(openMode)); |
5180 #ifdef __win32__ |
5176 #ifdef __win32__ |
5181 __stxWrapApiLeaveCritical(); |
5177 __stxWrapApiLeaveCritical(); |
5182 #endif |
5178 #endif |
5183 if (f != NULL) { |
5179 if (f != NULL) { |
5184 if (@global(FileOpenTrace) == true) { |
5180 if (@global(FileOpenTrace) == true) { |
5185 fprintf(stderr, "fdopen [ExternalStream] %d -> %"_lx_"\n", fd, (INT)f); |
5181 fprintf(stderr, "fdopen [ExternalStream] %d -> %"_lx_"\n", fd, (INT)f); |
5186 } |
5182 } |
5187 fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp); |
5183 fp = __MKFILEPOINTER(f); __INST(handle) = fp; __STORE(self, fp); |
5188 __INST(handleType) = @symbol(filePointer); |
5184 __INST(handleType) = @symbol(filePointer); |
5189 RETURN (self); |
5185 RETURN (self); |
5190 } |
5186 } |
5191 err:; |
5187 err:; |
5192 %}. |
5188 %}. |
5193 ^ self primitiveFailed |
5189 ^ self primitiveFailed |
5194 ! |
5190 ! |
5230 if ((__INST(handleType) == nil) |
5226 if ((__INST(handleType) == nil) |
5231 || (__INST(handleType) == @symbol(filePointer)) |
5227 || (__INST(handleType) == @symbol(filePointer)) |
5232 || (__INST(handleType) == @symbol(socketFilePointer)) |
5228 || (__INST(handleType) == @symbol(socketFilePointer)) |
5233 || (__INST(handleType) == @symbol(socketHandle)) |
5229 || (__INST(handleType) == @symbol(socketHandle)) |
5234 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5230 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5235 if (((fp = __INST(handle)) != nil) |
5231 if (((fp = __INST(handle)) != nil) |
5236 && (__INST(mode) != @symbol(writeonly)) |
5232 && (__INST(mode) != @symbol(writeonly)) |
5237 ) { |
5233 ) { |
5238 f = __FILEVal(fp); |
5234 f = __FILEVal(fp); |
5239 |
5235 |
5240 _buffered = (__INST(buffered) == true); |
5236 _buffered = (__INST(buffered) == true); |
5241 if (_buffered) { |
5237 if (_buffered) { |
5242 __READING__(f) |
5238 __READING__(f) |
5243 } |
5239 } |
5244 __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); |
5240 __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); |
5245 |
5241 |
5246 if (ret > 0) { |
5242 if (ret > 0) { |
5247 RETURN(nil) |
5243 RETURN(nil) |
5248 } |
5244 } |
5249 if (ret < 0) { |
5245 if (ret < 0) { |
5250 RETURN(__mkSmallInteger(__threadErrno)); |
5246 RETURN(__mkSmallInteger(__threadErrno)); |
5251 } else /* ret == 0 */ { |
5247 } else /* ret == 0 */ { |
5252 RETURN(__mkSmallInteger(0)); /* EOF */ |
5248 RETURN(__mkSmallInteger(0)); /* EOF */ |
5253 } |
5249 } |
5254 } |
5250 } |
5255 } |
5251 } |
5256 %}. |
5252 %}. |
5257 ! |
5253 ! |
5258 |
5254 |
5259 numAvailable |
5255 numAvailable |
5273 %{ |
5269 %{ |
5274 #ifdef __SCHTEAM__ |
5270 #ifdef __SCHTEAM__ |
5275 STObject handle = self.instVarAt(I_handle); |
5271 STObject handle = self.instVarAt(I_handle); |
5276 |
5272 |
5277 if (handle != STObject.Nil) { |
5273 if (handle != STObject.Nil) { |
5278 STObject next; |
5274 STObject next; |
5279 |
5275 |
5280 if (self.instVarAt(I_binary) == STObject.True) { |
5276 if (self.instVarAt(I_binary) == STObject.True) { |
5281 next = handle.nextByte(); |
5277 next = handle.nextByte(); |
5282 } else { |
5278 } else { |
5283 next = handle.nextChar(); |
5279 next = handle.nextChar(); |
5284 } |
5280 } |
5285 if (next != STObject.EOF) { |
5281 if (next != STObject.EOF) { |
5286 self.instVarAt_put(I_position, STObject.Nil); |
5282 self.instVarAt_put(I_position, STObject.Nil); |
5287 return __c__._RETURN( next ); |
5283 return __c__._RETURN( next ); |
5288 } |
5284 } |
5289 self.instVarAt_put(I_hitEOF, STObject.True); |
5285 self.instVarAt_put(I_hitEOF, STObject.True); |
5290 } |
5286 } |
5291 #else |
5287 #else |
5292 FILEPOINTER f; |
5288 FILEPOINTER f; |
5293 int ret, _buffered; |
5289 int ret, _buffered; |
5294 OBJ pos, fp; |
5290 OBJ pos, fp; |
5298 if ((__INST(handleType) == nil) |
5294 if ((__INST(handleType) == nil) |
5299 || (__INST(handleType) == @symbol(filePointer)) |
5295 || (__INST(handleType) == @symbol(filePointer)) |
5300 || (__INST(handleType) == @symbol(socketFilePointer)) |
5296 || (__INST(handleType) == @symbol(socketFilePointer)) |
5301 || (__INST(handleType) == @symbol(socketHandle)) |
5297 || (__INST(handleType) == @symbol(socketHandle)) |
5302 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5298 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5303 if (((fp = __INST(handle)) != nil) |
5299 if (((fp = __INST(handle)) != nil) |
5304 && (__INST(mode) != @symbol(writeonly)) |
5300 && (__INST(mode) != @symbol(writeonly)) |
5305 ) { |
5301 ) { |
5306 f = __FILEVal(fp); |
5302 f = __FILEVal(fp); |
5307 |
5303 |
5308 _buffered = (__INST(buffered) == true); |
5304 _buffered = (__INST(buffered) == true); |
5309 if (_buffered) { |
5305 if (_buffered) { |
5310 __READING__(f) |
5306 __READING__(f) |
5311 } |
5307 } |
5312 __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); |
5308 __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); |
5313 |
5309 |
5314 if (ret > 0) { |
5310 if (ret > 0) { |
5315 pos = __INST(position); |
5311 pos = __INST(position); |
5316 if (__isSmallInteger(pos)) { |
5312 if (__isSmallInteger(pos)) { |
5317 OBJ t; |
5313 OBJ t; |
5318 |
5314 |
5319 t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); |
5315 t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); |
5320 } else { |
5316 } else { |
5321 __INST(position) = nil; /* i.e. do not know */ |
5317 __INST(position) = nil; /* i.e. do not know */ |
5322 } |
5318 } |
5323 if (__INST(binary) == true) { |
5319 if (__INST(binary) == true) { |
5324 RETURN ( __mkSmallInteger(ch) ); |
5320 RETURN ( __mkSmallInteger(ch) ); |
5325 } |
5321 } |
5326 RETURN ( __MKCHARACTER(ch) ); |
5322 RETURN ( __MKCHARACTER(ch) ); |
5327 } |
5323 } |
5328 |
5324 |
5329 __INST(position) = nil; |
5325 __INST(position) = nil; |
5330 if (ret < 0) { |
5326 if (ret < 0) { |
5331 error = __mkSmallInteger(__threadErrno); |
5327 error = __mkSmallInteger(__threadErrno); |
5332 } else /* ret == 0 */ { |
5328 } else /* ret == 0 */ { |
5333 __INST(hitEOF) = true; |
5329 __INST(hitEOF) = true; |
5334 } |
5330 } |
5335 } |
5331 } |
5336 } |
5332 } |
5337 #endif /* not SCHTEAM */ |
5333 #endif /* not SCHTEAM */ |
5338 %}. |
5334 %}. |
5339 hitEOF ifTrue:[^ self pastEndRead]. |
5335 hitEOF ifTrue:[^ self pastEndRead]. |
5340 error notNil ifTrue:[ |
5336 error notNil ifTrue:[ |
5341 lastErrorNumber := error. |
5337 lastErrorNumber := error. |
5342 ^ self readError:error |
5338 ^ self readError:error |
5343 ]. |
5339 ]. |
5344 handle isNil ifTrue:[^ self errorNotOpen]. |
5340 handle isNil ifTrue:[^ self errorNotOpen]. |
5345 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5341 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5346 |
5342 |
5347 readAhead notNil ifTrue:[ |
5343 readAhead notNil ifTrue:[ |
5348 c := readAhead. |
5344 c := readAhead. |
5349 readAhead := nil. |
5345 readAhead := nil. |
5350 ^ c. |
5346 ^ c. |
5351 ]. |
5347 ]. |
5352 |
5348 |
5353 "unknown handleType - future" |
5349 "unknown handleType - future" |
5354 c := self nextByteFromFile:handle. |
5350 c := self nextByteFromFile:handle. |
5355 c isNil ifTrue:[ |
5351 c isNil ifTrue:[ |
5356 ^ self pastEndRead. |
5352 ^ self pastEndRead. |
5357 ]. |
5353 ]. |
5358 binary ifTrue:[ |
5354 binary ifTrue:[ |
5359 ^ c |
5355 ^ c |
5360 ]. |
5356 ]. |
5361 ^ Character value:c |
5357 ^ Character value:c |
5362 ! |
5358 ! |
5363 |
5359 |
5364 next:count |
5360 next:count |
5369 |
5365 |
5370 coll := self contentsSpecies uninitializedNew:count. |
5366 coll := self contentsSpecies uninitializedNew:count. |
5371 nRead := self nextBytes:count into:coll startingAt:1. |
5367 nRead := self nextBytes:count into:coll startingAt:1. |
5372 |
5368 |
5373 nRead ~~ count ifTrue:[ |
5369 nRead ~~ count ifTrue:[ |
5374 "/ for readStream protocol compatibility, |
5370 "/ for readStream protocol compatibility, |
5375 "/ we must raise an exception here. |
5371 "/ we must raise an exception here. |
5376 ^ self pastEndRead |
5372 ^ self pastEndRead |
5377 ]. |
5373 ]. |
5378 ^ coll |
5374 ^ coll |
5379 |
5375 |
5380 "Modified: 11.1.1997 / 17:44:17 / cg" |
5376 "Modified: 11.1.1997 / 17:44:17 / cg" |
5381 ! |
5377 ! |
5397 if ((__INST(handleType) == nil) |
5393 if ((__INST(handleType) == nil) |
5398 || (__INST(handleType) == @symbol(filePointer)) |
5394 || (__INST(handleType) == @symbol(filePointer)) |
5399 || (__INST(handleType) == @symbol(socketFilePointer)) |
5395 || (__INST(handleType) == @symbol(socketFilePointer)) |
5400 || (__INST(handleType) == @symbol(socketHandle)) |
5396 || (__INST(handleType) == @symbol(socketHandle)) |
5401 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5397 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5402 if (((fp = __INST(handle)) != nil) |
5398 if (((fp = __INST(handle)) != nil) |
5403 && (__INST(mode) != @symbol(writeonly)) |
5399 && (__INST(mode) != @symbol(writeonly)) |
5404 ) { |
5400 ) { |
5405 f = __FILEVal(fp); |
5401 f = __FILEVal(fp); |
5406 |
5402 |
5407 _buffered = (__INST(buffered) == true); |
5403 _buffered = (__INST(buffered) == true); |
5408 if (_buffered) { |
5404 if (_buffered) { |
5409 __READING__(f) |
5405 __READING__(f) |
5410 } |
5406 } |
5411 __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); |
5407 __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); |
5412 |
5408 |
5413 if (ret > 0) { |
5409 if (ret > 0) { |
5414 pos = __INST(position); |
5410 pos = __INST(position); |
5415 if (__isSmallInteger(pos)) { |
5411 if (__isSmallInteger(pos)) { |
5416 OBJ t; |
5412 OBJ t; |
5417 |
5413 |
5418 t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); |
5414 t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); |
5419 } else { |
5415 } else { |
5420 __INST(position) = nil; /* i.e. do not know */ |
5416 __INST(position) = nil; /* i.e. do not know */ |
5421 } |
5417 } |
5422 if (__INST(binary) == true) { |
5418 if (__INST(binary) == true) { |
5423 RETURN ( __mkSmallInteger(ch) ); |
5419 RETURN ( __mkSmallInteger(ch) ); |
5424 } |
5420 } |
5425 RETURN ( __MKCHARACTER(ch) ); |
5421 RETURN ( __MKCHARACTER(ch) ); |
5426 } |
5422 } |
5427 |
5423 |
5428 __INST(position) = nil; |
5424 __INST(position) = nil; |
5429 if (ret < 0) { |
5425 if (ret < 0) { |
5430 error = __mkSmallInteger(__threadErrno); |
5426 error = __mkSmallInteger(__threadErrno); |
5431 } else /* ret == 0 */ { |
5427 } else /* ret == 0 */ { |
5432 __INST(hitEOF) = true; |
5428 __INST(hitEOF) = true; |
5433 } |
5429 } |
5434 } |
5430 } |
5435 } |
5431 } |
5436 %}. |
5432 %}. |
5437 hitEOF ifTrue:[^ nil]. |
5433 hitEOF ifTrue:[^ nil]. |
5438 error notNil ifTrue:[ |
5434 error notNil ifTrue:[ |
5439 lastErrorNumber := error. |
5435 lastErrorNumber := error. |
5440 ^ self readError:error. |
5436 ^ self readError:error. |
5441 ]. |
5437 ]. |
5442 handle isNil ifTrue:[^ self errorNotOpen]. |
5438 handle isNil ifTrue:[^ self errorNotOpen]. |
5443 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5439 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5444 |
5440 |
5445 readAhead notNil ifTrue:[ |
5441 readAhead notNil ifTrue:[ |
5446 c := readAhead. |
5442 c := readAhead. |
5447 readAhead := nil. |
5443 readAhead := nil. |
5448 ^ c. |
5444 ^ c. |
5449 ]. |
5445 ]. |
5450 |
5446 |
5451 "unknown handleType - future" |
5447 "unknown handleType - future" |
5452 c := self nextByteFromFile:handle. |
5448 c := self nextByteFromFile:handle. |
5453 c isNil ifTrue:[ |
5449 c isNil ifTrue:[ |
5454 ^ nil. |
5450 ^ nil. |
5455 ]. |
5451 ]. |
5456 binary == true ifTrue:[ |
5452 binary == true ifTrue:[ |
5457 ^ c |
5453 ^ c |
5458 ]. |
5454 ]. |
5459 ^ Character value:c |
5455 ^ Character value:c |
5460 ! |
5456 ! |
5461 |
5457 |
5462 peek |
5458 peek |
5472 int ret, _buffered; |
5468 int ret, _buffered; |
5473 OBJ fp; |
5469 OBJ fp; |
5474 OBJ ra; |
5470 OBJ ra; |
5475 |
5471 |
5476 if ((ra = __INST(readAhead)) != nil) { |
5472 if ((ra = __INST(readAhead)) != nil) { |
5477 if (__INST(binary) == true) { |
5473 if (__INST(binary) == true) { |
5478 RETURN ( ra ); |
5474 RETURN ( ra ); |
5479 } |
5475 } |
5480 c = __intVal(ra); |
5476 c = __intVal(ra); |
5481 RETURN ( __MKCHARACTER(c) ); |
5477 RETURN ( __MKCHARACTER(c) ); |
5482 } |
5478 } |
5483 |
5479 |
5484 __INST(lastErrorNumber) = nil; |
5480 __INST(lastErrorNumber) = nil; |
5485 |
5481 |
5486 if ((__INST(handleType) == nil) |
5482 if ((__INST(handleType) == nil) |
5487 || (__INST(handleType) == @symbol(filePointer)) |
5483 || (__INST(handleType) == @symbol(filePointer)) |
5488 || (__INST(handleType) == @symbol(socketFilePointer)) |
5484 || (__INST(handleType) == @symbol(socketFilePointer)) |
5489 || (__INST(handleType) == @symbol(socketHandle)) |
5485 || (__INST(handleType) == @symbol(socketHandle)) |
5490 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5486 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5491 if (((fp = __INST(handle)) != nil) |
5487 if (((fp = __INST(handle)) != nil) |
5492 && (__INST(mode) != @symbol(writeonly)) |
5488 && (__INST(mode) != @symbol(writeonly)) |
5493 ) { |
5489 ) { |
5494 f = __FILEVal(fp); |
5490 f = __FILEVal(fp); |
5495 _buffered = (__INST(buffered) == true); |
5491 _buffered = (__INST(buffered) == true); |
5496 if (_buffered) { |
5492 if (_buffered) { |
5497 __READING__(f) |
5493 __READING__(f) |
5498 } |
5494 } |
5499 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5495 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5500 |
5496 |
5501 if (ret > 0) { |
5497 if (ret > 0) { |
5502 __UNGETC__(c, f, _buffered); |
5498 __UNGETC__(c, f, _buffered); |
5503 |
5499 |
5504 if (__INST(binary) == true) { |
5500 if (__INST(binary) == true) { |
5505 RETURN ( __mkSmallInteger(c) ); |
5501 RETURN ( __mkSmallInteger(c) ); |
5506 } |
5502 } |
5507 RETURN ( __MKCHARACTER(c) ); |
5503 RETURN ( __MKCHARACTER(c) ); |
5508 } |
5504 } |
5509 if (ret < 0) { |
5505 if (ret < 0) { |
5510 error = __mkSmallInteger(__threadErrno); |
5506 error = __mkSmallInteger(__threadErrno); |
5511 } else /* ret == 0 */ { |
5507 } else /* ret == 0 */ { |
5512 __INST(hitEOF) = true; |
5508 __INST(hitEOF) = true; |
5513 } |
5509 } |
5514 } |
5510 } |
5515 } |
5511 } |
5516 %}. |
5512 %}. |
5517 hitEOF ifTrue:[^ self pastEndRead]. |
5513 hitEOF ifTrue:[^ self pastEndRead]. |
5518 error notNil ifTrue:[ |
5514 error notNil ifTrue:[ |
5519 lastErrorNumber := error. |
5515 lastErrorNumber := error. |
5520 ^ self readError:error. |
5516 ^ self readError:error. |
5521 ]. |
5517 ]. |
5522 handle isNil ifTrue:[^ self errorNotOpen]. |
5518 handle isNil ifTrue:[^ self errorNotOpen]. |
5523 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5519 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5524 |
5520 |
5525 readAhead isNil ifTrue:[ |
5521 readAhead isNil ifTrue:[ |
5526 readAhead := self nextOrNil. |
5522 readAhead := self nextOrNil. |
5527 readAhead isNil ifTrue:[ |
5523 readAhead isNil ifTrue:[ |
5528 ^ self pastEndRead. |
5524 ^ self pastEndRead. |
5529 ]. |
5525 ]. |
5530 ]. |
5526 ]. |
5531 ^ readAhead |
5527 ^ readAhead |
5532 ! |
5528 ! |
5533 |
5529 |
5534 peekOrNil |
5530 peekOrNil |
5544 int ret, _buffered; |
5540 int ret, _buffered; |
5545 OBJ fp; |
5541 OBJ fp; |
5546 OBJ ra; |
5542 OBJ ra; |
5547 |
5543 |
5548 if ((ra = __INST(readAhead)) != nil) { |
5544 if ((ra = __INST(readAhead)) != nil) { |
5549 if (__INST(binary) == true) { |
5545 if (__INST(binary) == true) { |
5550 RETURN ( ra ); |
5546 RETURN ( ra ); |
5551 } |
5547 } |
5552 c = __intVal(ra); |
5548 c = __intVal(ra); |
5553 RETURN ( __MKCHARACTER(c) ); |
5549 RETURN ( __MKCHARACTER(c) ); |
5554 } |
5550 } |
5555 |
5551 |
5556 __INST(lastErrorNumber) = nil; |
5552 __INST(lastErrorNumber) = nil; |
5557 |
5553 |
5558 if ((__INST(handleType) == nil) |
5554 if ((__INST(handleType) == nil) |
5559 || (__INST(handleType) == @symbol(filePointer)) |
5555 || (__INST(handleType) == @symbol(filePointer)) |
5560 || (__INST(handleType) == @symbol(socketFilePointer)) |
5556 || (__INST(handleType) == @symbol(socketFilePointer)) |
5561 || (__INST(handleType) == @symbol(socketHandle)) |
5557 || (__INST(handleType) == @symbol(socketHandle)) |
5562 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5558 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5563 if (((fp = __INST(handle)) != nil) |
5559 if (((fp = __INST(handle)) != nil) |
5564 && (__INST(mode) != @symbol(writeonly)) |
5560 && (__INST(mode) != @symbol(writeonly)) |
5565 ) { |
5561 ) { |
5566 f = __FILEVal(fp); |
5562 f = __FILEVal(fp); |
5567 _buffered = (__INST(buffered) == true); |
5563 _buffered = (__INST(buffered) == true); |
5568 if (_buffered) { |
5564 if (_buffered) { |
5569 __READING__(f) |
5565 __READING__(f) |
5570 } |
5566 } |
5571 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5567 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5572 |
5568 |
5573 if (ret > 0) { |
5569 if (ret > 0) { |
5574 __UNGETC__(c, f, _buffered); |
5570 __UNGETC__(c, f, _buffered); |
5575 |
5571 |
5576 if (__INST(binary) == true) { |
5572 if (__INST(binary) == true) { |
5577 RETURN ( __mkSmallInteger(c) ); |
5573 RETURN ( __mkSmallInteger(c) ); |
5578 } |
5574 } |
5579 RETURN ( __MKCHARACTER(c) ); |
5575 RETURN ( __MKCHARACTER(c) ); |
5580 } |
5576 } |
5581 if (ret < 0) { |
5577 if (ret < 0) { |
5582 error = __mkSmallInteger(__threadErrno); |
5578 error = __mkSmallInteger(__threadErrno); |
5583 } else /* ret == 0 */ { |
5579 } else /* ret == 0 */ { |
5584 __INST(hitEOF) = true; |
5580 __INST(hitEOF) = true; |
5585 } |
5581 } |
5586 } |
5582 } |
5587 } |
5583 } |
5588 %}. |
5584 %}. |
5589 hitEOF ifTrue:[^ nil]. |
5585 hitEOF ifTrue:[^ nil]. |
5590 error notNil ifTrue:[ |
5586 error notNil ifTrue:[ |
5591 lastErrorNumber := error. |
5587 lastErrorNumber := error. |
5592 ^ self readError:error. |
5588 ^ self readError:error. |
5593 ]. |
5589 ]. |
5594 handle isNil ifTrue:[^ self errorNotOpen]. |
5590 handle isNil ifTrue:[^ self errorNotOpen]. |
5595 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5591 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
5596 |
5592 |
5597 readAhead isNil ifTrue:[ |
5593 readAhead isNil ifTrue:[ |
5598 readAhead := self nextOrNil. |
5594 readAhead := self nextOrNil. |
5599 ]. |
5595 ]. |
5600 ^ readAhead |
5596 ^ readAhead |
5601 ! |
5597 ! |
5602 |
5598 |
5603 upToEnd |
5599 upToEnd |
5613 chunkSize := 4096. |
5609 chunkSize := 4096. |
5614 byteCount := 0. |
5610 byteCount := 0. |
5615 contentsSpecies := self contentsSpecies. |
5611 contentsSpecies := self contentsSpecies. |
5616 |
5612 |
5617 [self atEnd] whileFalse:[ |
5613 [self atEnd] whileFalse:[ |
5618 |chunk cnt| |
5614 |chunk cnt| |
5619 |
5615 |
5620 chunk := contentsSpecies uninitializedNew:chunkSize. |
5616 chunk := contentsSpecies uninitializedNew:chunkSize. |
5621 cnt := self nextBytes:chunkSize into:chunk startingAt:1. |
5617 cnt := self nextBytes:chunkSize into:chunk startingAt:1. |
5622 cnt ~~ 0 ifTrue:[ |
5618 cnt ~~ 0 ifTrue:[ |
5623 chunksAndCounts isNil ifTrue:[ |
5619 chunksAndCounts isNil ifTrue:[ |
5624 (cnt < chunkSize and:[self atEnd]) ifTrue:[ |
5620 (cnt < chunkSize and:[self atEnd]) ifTrue:[ |
5625 "all data is in a single chunk, so we are done" |
5621 "all data is in a single chunk, so we are done" |
5626 ^ chunk copyFrom:1 to:cnt. |
5622 ^ chunk copyFrom:1 to:cnt. |
5627 ]. |
5623 ]. |
5628 chunksAndCounts := OrderedCollection new. |
5624 chunksAndCounts := OrderedCollection new. |
5629 ]. |
5625 ]. |
5630 chunksAndCounts add:chunk; add:cnt. |
5626 chunksAndCounts add:chunk; add:cnt. |
5631 byteCount := byteCount + cnt. |
5627 byteCount := byteCount + cnt. |
5632 ] |
5628 ] |
5633 ]. |
5629 ]. |
5634 |
5630 |
5635 "now, create one big array" |
5631 "now, create one big array" |
5636 data := contentsSpecies uninitializedNew:byteCount. |
5632 data := contentsSpecies uninitializedNew:byteCount. |
5637 offset := 1. |
5633 offset := 1. |
5638 1 to:chunksAndCounts size by:2 do:[:index | |
5634 1 to:chunksAndCounts size by:2 do:[:index | |
5639 |chunk cnt| |
5635 |chunk cnt| |
5640 |
5636 |
5641 chunk := chunksAndCounts at:index. |
5637 chunk := chunksAndCounts at:index. |
5642 cnt := chunksAndCounts at:index+1. |
5638 cnt := chunksAndCounts at:index+1. |
5643 data replaceFrom:offset to:(offset + cnt - 1) with:chunk startingAt:1. |
5639 data replaceFrom:offset to:(offset + cnt - 1) with:chunk startingAt:1. |
5644 offset := offset + cnt |
5640 offset := offset + cnt |
5645 ]. |
5641 ]. |
5646 ^ data |
5642 ^ data |
5647 |
5643 |
5648 |
5644 |
5649 " |
5645 " |
5650 '/dev/null' asFilename readStream upToEnd |
5646 '/dev/null' asFilename readStream upToEnd |
5651 '/proc/self/stat' asFilename readStream upToEnd |
5647 '/proc/self/stat' asFilename readStream upToEnd |
5652 'librun.so' asFilename readStream binary upToEnd |
5648 'librun.so' asFilename readStream binary upToEnd |
5653 |
5649 |
5654 self assert:('smalltalk.rc' asFilename readStream upToEnd size) |
5650 self assert:('smalltalk.rc' asFilename readStream upToEnd size) |
5655 = ('smalltalk.rc' asFilename readStream size) |
5651 = ('smalltalk.rc' asFilename readStream size) |
5656 " |
5652 " |
5657 |
5653 |
5658 "Modified (format): / 09-05-2018 / 20:09:31 / stefan" |
5654 "Modified (format): / 09-05-2018 / 20:09:31 / stefan" |
5659 ! ! |
5655 ! ! |
5660 |
5656 |
5690 %{ |
5686 %{ |
5691 OBJ fp, lim; |
5687 OBJ fp, lim; |
5692 char c; |
5688 char c; |
5693 |
5689 |
5694 if (__INST(hitEOF) == true) { |
5690 if (__INST(hitEOF) == true) { |
5695 RETURN (true); |
5691 RETURN (true); |
5696 } |
5692 } |
5697 lim = __INST(readLimit); |
5693 lim = __INST(readLimit); |
5698 if (lim != nil && __signedLongIntVal(__INST(position)) >= __signedLongIntVal(lim)) { |
5694 if (lim != nil && __signedLongIntVal(__INST(position)) >= __signedLongIntVal(lim)) { |
5699 RETURN (true); |
5695 RETURN (true); |
5700 } |
5696 } |
5701 |
5697 |
5702 __INST(lastErrorNumber) = nil; |
5698 __INST(lastErrorNumber) = nil; |
5703 |
5699 |
5704 if ((__INST(handleType) == nil) |
5700 if ((__INST(handleType) == nil) |
5705 || (__INST(handleType) == @symbol(filePointer)) |
5701 || (__INST(handleType) == @symbol(filePointer)) |
5706 || (__INST(handleType) == @symbol(socketFilePointer)) |
5702 || (__INST(handleType) == @symbol(socketFilePointer)) |
5707 || (__INST(handleType) == @symbol(socketHandle)) |
5703 || (__INST(handleType) == @symbol(socketHandle)) |
5708 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5704 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
5709 if ((fp = __INST(handle)) != nil) { |
5705 if ((fp = __INST(handle)) != nil) { |
5710 int _buffered = (__INST(buffered) == true); |
5706 int _buffered = (__INST(buffered) == true); |
5711 int ret; |
5707 int ret; |
5712 FILEPOINTER f = __FILEVal(fp); |
5708 FILEPOINTER f = __FILEVal(fp); |
5713 |
5709 |
5714 if (_buffered) { |
5710 if (_buffered) { |
5715 __READING__(f); |
5711 __READING__(f); |
5716 } else if (__INST(readAhead) != nil) { |
5712 } else if (__INST(readAhead) != nil) { |
5717 RETURN (false); |
5713 RETURN (false); |
5718 } |
5714 } |
5719 |
5715 |
5720 /* |
5716 /* |
5721 * read ahead ... |
5717 * read ahead ... |
5722 */ |
5718 */ |
5723 do { |
5719 do { |
5724 #ifdef __win32__ |
5720 #ifdef __win32__ |
5725 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5721 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5726 #else /* not __win32__ */ |
5722 #else /* not __win32__ */ |
5727 __BEGIN_INTERRUPTABLE__ |
5723 __BEGIN_INTERRUPTABLE__ |
5728 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5724 __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); |
5729 __END_INTERRUPTABLE__ |
5725 __END_INTERRUPTABLE__ |
5730 #endif /* not __win32__ */ |
5726 #endif /* not __win32__ */ |
5731 } while ((ret < 0) && (__threadErrno == EINTR)); |
5727 } while ((ret < 0) && (__threadErrno == EINTR)); |
5732 if (ret > 0) { |
5728 if (ret > 0) { |
5733 __UNGETC__(c&0xff, f, _buffered); |
5729 __UNGETC__(c&0xff, f, _buffered); |
5734 RETURN (false); |
5730 RETURN (false); |
5735 } |
5731 } |
5736 if (ret == 0) { |
5732 if (ret == 0) { |
5737 __INST(hitEOF) = true; |
5733 __INST(hitEOF) = true; |
5738 RETURN (true); |
5734 RETURN (true); |
5739 } |
5735 } |
5740 /* ret < 0 -> error */ |
5736 /* ret < 0 -> error */ |
5741 __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno); |
5737 __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno); |
5742 } |
5738 } |
5743 // we do not raise an error here - the next read operation will raise the error. |
5739 // we do not raise an error here - the next read operation will raise the error. |
5744 RETURN(false); |
5740 RETURN(false); |
5745 } |
5741 } |
5746 %}. |
5742 %}. |
5747 |
5743 |
5748 "/ we come here if the handle type is unknown |
5744 "/ we come here if the handle type is unknown |
5749 "/ migration support |
5745 "/ migration support |
5837 "answer the number of bytes available for reading" |
5833 "answer the number of bytes available for reading" |
5838 |
5834 |
5839 |available| |
5835 |available| |
5840 |
5836 |
5841 handle isNil ifTrue:[ |
5837 handle isNil ifTrue:[ |
5842 ^ self errorNotOpen |
5838 ^ self errorNotOpen |
5843 ]. |
5839 ]. |
5844 mode == #writeonly ifTrue:[ |
5840 mode == #writeonly ifTrue:[ |
5845 ^ self errorWriteOnly |
5841 ^ self errorWriteOnly |
5846 ]. |
5842 ]. |
5847 available := OperatingSystem numAvailableForReadOn:self fileHandle. |
5843 available := OperatingSystem numAvailableForReadOn:self fileHandle. |
5848 readAhead notNil ifTrue:[ |
5844 readAhead notNil ifTrue:[ |
5849 available := available + 1 |
5845 available := available + 1 |
5850 ]. |
5846 ]. |
5851 ^ available. |
5847 ^ available. |
5852 |
5848 |
5853 " |
5849 " |
5854 '/etc/hosts' asFilename readStream numAvailableForRead |
5850 '/etc/hosts' asFilename readStream numAvailableForRead |
5855 " |
5851 " |
5856 ! |
5852 ! |
5857 |
5853 |
5858 readWaitWithTimeoutMs:timeoutOrNil |
5854 readWaitWithTimeoutMs:timeoutOrNil |
5859 "suspend the current process, until the receiver |
5855 "suspend the current process, until the receiver |
5882 Smalltalk isInitialized ifFalse:[ ^ false ]. |
5878 Smalltalk isInitialized ifFalse:[ ^ false ]. |
5883 |
5879 |
5884 wasBlocked := OperatingSystem blockInterrupts. |
5880 wasBlocked := OperatingSystem blockInterrupts. |
5885 inputSema := Semaphore name:'readWait'. |
5881 inputSema := Semaphore name:'readWait'. |
5886 [ |
5882 [ |
5887 Processor signal:inputSema onInput:fd. |
5883 Processor signal:inputSema onInput:fd. |
5888 hasTimedout := (inputSema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5884 hasTimedout := (inputSema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5889 ] ifCurtailed:[ |
5885 ] ifCurtailed:[ |
5890 Processor disableSemaphore:inputSema. |
5886 Processor disableSemaphore:inputSema. |
5891 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5887 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5892 ]. |
5888 ]. |
5893 hasTimedout ifTrue:[ |
5889 hasTimedout ifTrue:[ |
5894 Processor disableSemaphore:inputSema. |
5890 Processor disableSemaphore:inputSema. |
5895 ]. |
5891 ]. |
5896 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5892 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5897 ^ hasTimedout |
5893 ^ hasTimedout |
5898 |
5894 |
5899 "Modified: / 09-08-2017 / 11:53:58 / cg" |
5895 "Modified: / 09-08-2017 / 11:53:58 / cg" |
5908 |
5904 |
5909 |fd sema hasTimedout wasBlocked| |
5905 |fd sema hasTimedout wasBlocked| |
5910 |
5906 |
5911 readAhead notNil ifTrue:[^ false]. |
5907 readAhead notNil ifTrue:[^ false]. |
5912 handle isNil ifTrue:[ |
5908 handle isNil ifTrue:[ |
5913 ^ self errorNotOpen |
5909 ^ self errorNotOpen |
5914 ]. |
5910 ]. |
5915 |
5911 |
5916 fd := self fileHandle. |
5912 fd := self fileHandle. |
5917 (OperatingSystem readWriteCheck:fd) ifTrue:[^ false]. |
5913 (OperatingSystem readWriteCheck:fd) ifTrue:[^ false]. |
5918 |
5914 |
5919 wasBlocked := OperatingSystem blockInterrupts. |
5915 wasBlocked := OperatingSystem blockInterrupts. |
5920 sema := Semaphore name:'readWriteWait'. |
5916 sema := Semaphore name:'readWriteWait'. |
5921 [ |
5917 [ |
5922 Processor |
5918 Processor |
5923 signal:sema onOutput:fd; |
5919 signal:sema onOutput:fd; |
5924 signal:sema onInput:fd. |
5920 signal:sema onInput:fd. |
5925 hasTimedout := (sema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5921 hasTimedout := (sema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5926 ] ifCurtailed:[ |
5922 ] ifCurtailed:[ |
5927 Processor disableSemaphore:sema. |
5923 Processor disableSemaphore:sema. |
5928 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5924 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5929 ]. |
5925 ]. |
5930 hasTimedout ifTrue:[ |
5926 hasTimedout ifTrue:[ |
5931 Processor disableSemaphore:sema. |
5927 Processor disableSemaphore:sema. |
5932 ]. |
5928 ]. |
5933 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5929 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5934 ^ hasTimedout |
5930 ^ hasTimedout |
5935 |
5931 |
5936 "Modified: / 09-08-2017 / 11:54:03 / cg" |
5932 "Modified: / 09-08-2017 / 11:54:03 / cg" |
5944 The other threads are not affected by the wait." |
5940 The other threads are not affected by the wait." |
5945 |
5941 |
5946 |fd sema hasTimedout wasBlocked| |
5942 |fd sema hasTimedout wasBlocked| |
5947 |
5943 |
5948 handle isNil ifTrue:[ |
5944 handle isNil ifTrue:[ |
5949 ^ self errorNotOpen |
5945 ^ self errorNotOpen |
5950 ]. |
5946 ]. |
5951 |
5947 |
5952 fd := self fileHandle. |
5948 fd := self fileHandle. |
5953 (OperatingSystem writeExceptionCheck:fd) ifTrue:[^ false]. |
5949 (OperatingSystem writeExceptionCheck:fd) ifTrue:[^ false]. |
5954 |
5950 |
5955 wasBlocked := OperatingSystem blockInterrupts. |
5951 wasBlocked := OperatingSystem blockInterrupts. |
5956 sema := Semaphore name:'writeExceptionWait'. |
5952 sema := Semaphore name:'writeExceptionWait'. |
5957 [ |
5953 [ |
5958 Processor |
5954 Processor |
5959 signal:sema onOutput:fd; |
5955 signal:sema onOutput:fd; |
5960 signal:sema onException:fd. |
5956 signal:sema onException:fd. |
5961 hasTimedout := (sema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5957 hasTimedout := (sema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5962 ] ifCurtailed:[ |
5958 ] ifCurtailed:[ |
5963 Processor disableSemaphore:sema. |
5959 Processor disableSemaphore:sema. |
5964 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5960 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5965 ]. |
5961 ]. |
5966 hasTimedout ifTrue:[ |
5962 hasTimedout ifTrue:[ |
5967 Processor disableSemaphore:sema. |
5963 Processor disableSemaphore:sema. |
5968 ]. |
5964 ]. |
5969 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5965 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5970 ^ hasTimedout |
5966 ^ hasTimedout |
5971 |
5967 |
5972 "Modified: / 09-08-2017 / 11:54:10 / cg" |
5968 "Modified: / 09-08-2017 / 11:54:10 / cg" |
5980 The other threads are not affected by the wait." |
5976 The other threads are not affected by the wait." |
5981 |
5977 |
5982 |fd outputSema hasTimedout wasBlocked| |
5978 |fd outputSema hasTimedout wasBlocked| |
5983 |
5979 |
5984 handle isNil ifTrue:[ |
5980 handle isNil ifTrue:[ |
5985 ^ self errorNotOpen |
5981 ^ self errorNotOpen |
5986 ]. |
5982 ]. |
5987 mode == #readonly ifTrue:[ |
5983 mode == #readonly ifTrue:[ |
5988 ^ self errorReadOnly |
5984 ^ self errorReadOnly |
5989 ]. |
5985 ]. |
5990 |
5986 |
5991 fd := self fileHandle. |
5987 fd := self fileHandle. |
5992 (OperatingSystem writeCheck:fd) ifTrue:[^ false]. |
5988 (OperatingSystem writeCheck:fd) ifTrue:[^ false]. |
5993 |
5989 |
5994 wasBlocked := OperatingSystem blockInterrupts. |
5990 wasBlocked := OperatingSystem blockInterrupts. |
5995 outputSema := Semaphore name:'writeWait'. |
5991 outputSema := Semaphore name:'writeWait'. |
5996 [ |
5992 [ |
5997 Processor signal:outputSema onOutput:fd. |
5993 Processor signal:outputSema onOutput:fd. |
5998 hasTimedout := (outputSema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5994 hasTimedout := (outputSema waitWithTimeoutMs:timeoutOrNil state:#ioWait) isNil. |
5999 ] ifCurtailed:[ |
5995 ] ifCurtailed:[ |
6000 Processor disableSemaphore:outputSema. |
5996 Processor disableSemaphore:outputSema. |
6001 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
5997 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
6002 ]. |
5998 ]. |
6003 hasTimedout ifTrue:[ |
5999 hasTimedout ifTrue:[ |
6004 Processor disableSemaphore:outputSema. |
6000 Processor disableSemaphore:outputSema. |
6005 ]. |
6001 ]. |
6006 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
6002 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
6007 ^ hasTimedout |
6003 ^ hasTimedout |
6008 |
6004 |
6009 "Modified: / 09-08-2017 / 11:54:14 / cg" |
6005 "Modified: / 09-08-2017 / 11:54:14 / cg" |
6019 if ((__INST(handleType) == nil) |
6015 if ((__INST(handleType) == nil) |
6020 || (__INST(handleType) == @symbol(filePointer)) |
6016 || (__INST(handleType) == @symbol(filePointer)) |
6021 || (__INST(handleType) == @symbol(socketHandle)) |
6017 || (__INST(handleType) == @symbol(socketHandle)) |
6022 || (__INST(handleType) == @symbol(socketFilePointer)) |
6018 || (__INST(handleType) == @symbol(socketFilePointer)) |
6023 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6019 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6024 OBJ fp; |
6020 OBJ fp; |
6025 |
6021 |
6026 __INST(lastErrorNumber) = nil; |
6022 __INST(lastErrorNumber) = nil; |
6027 if (((fp = __INST(handle)) != nil) |
6023 if (((fp = __INST(handle)) != nil) |
6028 && (__INST(mode) != @symbol(readonly)) |
6024 && (__INST(mode) != @symbol(readonly)) |
6029 && (__INST(binary) != true) |
6025 && (__INST(binary) != true) |
6030 ) { |
6026 ) { |
6031 FILEPOINTER f = __FILEVal(fp); |
6027 FILEPOINTER f = __FILEVal(fp); |
6032 int _buffered = (__INST(buffered) == true); |
6028 int _buffered = (__INST(buffered) == true); |
6033 int len, cnt; |
6029 int len, cnt; |
6034 char *cp; |
6030 char *cp; |
6035 |
6031 |
6036 if (_buffered) { |
6032 if (_buffered) { |
6037 __WRITING__(f) |
6033 __WRITING__(f) |
6038 } |
6034 } |
6039 { |
6035 { |
6040 OBJ mode = __INST(eolMode); |
6036 OBJ mode = __INST(eolMode); |
6041 |
6037 |
6042 if (mode == @symbol(cr)) { |
6038 if (mode == @symbol(cr)) { |
6043 cp = "\r"; len = 1; |
6039 cp = "\r"; len = 1; |
6044 } else if (mode == @symbol(crlf)) { |
6040 } else if (mode == @symbol(crlf)) { |
6045 cp = "\r\n"; len = 2; |
6041 cp = "\r\n"; len = 2; |
6046 } else if (mode == @symbol(eot)) { |
6042 } else if (mode == @symbol(eot)) { |
6047 cp = "\004"; len = 1; |
6043 cp = "\004"; len = 1; |
6048 } else if (mode == @symbol(etx)) { |
6044 } else if (mode == @symbol(etx)) { |
6049 cp = "\003"; len = 1; |
6045 cp = "\003"; len = 1; |
6050 } else { |
6046 } else { |
6051 cp = "\n"; len = 1; |
6047 cp = "\n"; len = 1; |
6052 } |
6048 } |
6053 } |
6049 } |
6054 #ifdef __win32__ |
6050 #ifdef __win32__ |
6055 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6051 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6056 cnt = __win32_fwrite(cp, 1, len, f); |
6052 cnt = __win32_fwrite(cp, 1, len, f); |
6057 } else |
6053 } else |
6058 #endif |
6054 #endif |
6059 { |
6055 { |
6060 __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType)); |
6056 __WRITEBYTES__(cnt, f, cp, len, _buffered, __INST(handleType)); |
6061 } |
6057 } |
6062 if (cnt == len) { |
6058 if (cnt == len) { |
6063 if (__isSmallInteger(__INST(position))) { |
6059 if (__isSmallInteger(__INST(position))) { |
6064 INT np = __intVal(__INST(position)) + len; |
6060 INT np = __intVal(__INST(position)) + len; |
6065 OBJ t; |
6061 OBJ t; |
6066 |
6062 |
6067 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6063 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6068 } else { |
6064 } else { |
6069 __INST(position) = nil; /* i.e: don't know */ |
6065 __INST(position) = nil; /* i.e: don't know */ |
6070 } |
6066 } |
6071 RETURN ( self ); |
6067 RETURN ( self ); |
6072 } |
6068 } |
6073 __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno); |
6069 __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno); |
6074 } |
6070 } |
6075 } |
6071 } |
6076 %}. |
6072 %}. |
6077 lastErrorNumber notNil ifTrue:[self writeError. ^ self]. |
6073 lastErrorNumber notNil ifTrue:[self writeError. ^ self]. |
6078 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
6074 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
6079 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
6075 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
6080 binary ifTrue:[self errorBinary. ^ self]. |
6076 binary ifTrue:[self errorBinary. ^ self]. |
6081 |
6077 |
6082 (eolMode == #cr) ifTrue:[ |
6078 (eolMode == #cr) ifTrue:[ |
6083 self nextPut:(Character return). |
6079 self nextPut:(Character return). |
6084 ^ self |
6080 ^ self |
6085 ]. |
6081 ]. |
6086 (eolMode == #crlf) ifTrue:[ |
6082 (eolMode == #crlf) ifTrue:[ |
6087 self nextPut:(Character return). |
6083 self nextPut:(Character return). |
6088 ]. |
6084 ]. |
6089 self nextPut:(Character nl). |
6085 self nextPut:(Character nl). |
6090 ^ self |
6086 ^ self |
6091 ! |
6087 ! |
6092 |
6088 |
6097 __INST(lastErrorNumber) = nil; |
6093 __INST(lastErrorNumber) = nil; |
6098 if ((__INST(handleType) == nil) |
6094 if ((__INST(handleType) == nil) |
6099 || (__INST(handleType) == @symbol(filePointer)) |
6095 || (__INST(handleType) == @symbol(filePointer)) |
6100 || (__INST(handleType) == @symbol(socketFilePointer)) |
6096 || (__INST(handleType) == @symbol(socketFilePointer)) |
6101 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6097 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6102 OBJ fp; |
6098 OBJ fp; |
6103 int _buffered = (__INST(buffered) == true); |
6099 int _buffered = (__INST(buffered) == true); |
6104 |
6100 |
6105 if ((fp = __INST(handle)) != nil) { |
6101 if ((fp = __INST(handle)) != nil) { |
6106 if (__INST(mode) != @symbol(readonly)) { |
6102 if (__INST(mode) != @symbol(readonly)) { |
6107 if (_buffered) { |
6103 if (_buffered) { |
6108 FILEPOINTER f = __FILEVal(fp); |
6104 FILEPOINTER f = __FILEVal(fp); |
6109 #ifdef __win32__ |
6105 #ifdef __win32__ |
6110 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6106 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6111 __win32_fflush(f); |
6107 __win32_fflush(f); |
6112 } else { |
6108 } else { |
6113 int rslt; |
6109 int rslt; |
6114 |
6110 |
6115 do { |
6111 do { |
6116 __threadErrno = 0; |
6112 __threadErrno = 0; |
6117 rslt = __STX_C_CALL1("fflush", fflush, f); |
6113 rslt = __STX_C_CALL1("fflush", fflush, f); |
6118 } while((rslt < 0) && (__threadErrno == EINTR)); |
6114 } while((rslt < 0) && (__threadErrno == EINTR)); |
6119 } |
6115 } |
6120 #else /* ! __win32__ */ |
6116 #else /* ! __win32__ */ |
6121 __BEGIN_INTERRUPTABLE__ |
6117 __BEGIN_INTERRUPTABLE__ |
6122 FFLUSH(f); |
6118 FFLUSH(f); |
6123 __END_INTERRUPTABLE__ |
6119 __END_INTERRUPTABLE__ |
6124 #endif /* ! __win32__ */ |
6120 #endif /* ! __win32__ */ |
6125 } |
6121 } |
6126 } |
6122 } |
6127 } |
6123 } |
6128 } |
6124 } |
6129 %} |
6125 %} |
6130 ! |
6126 ! |
6131 |
6127 |
6132 nextPut:aCharacter |
6128 nextPut:aCharacter |
6138 #ifdef __SCHTEAM__ |
6134 #ifdef __SCHTEAM__ |
6139 STObject handle = self.instVarAt(I_handle); |
6135 STObject handle = self.instVarAt(I_handle); |
6140 |
6136 |
6141 if ((handle != STObject.Nil) |
6137 if ((handle != STObject.Nil) |
6142 && (aCharacter.isSTCharacter())) { |
6138 && (aCharacter.isSTCharacter())) { |
6143 handle.writeChar( aCharacter ); |
6139 handle.writeChar( aCharacter ); |
6144 self.instVarAt_put(I_position, STObject.Nil); |
6140 self.instVarAt_put(I_position, STObject.Nil); |
6145 return __c__._RETURN_self(); |
6141 return __c__._RETURN_self(); |
6146 } |
6142 } |
6147 #else |
6143 #else |
6148 __INST(lastErrorNumber) = nil; |
6144 __INST(lastErrorNumber) = nil; |
6149 if ((__INST(handleType) == nil) |
6145 if ((__INST(handleType) == nil) |
6150 || (__INST(handleType) == @symbol(filePointer)) |
6146 || (__INST(handleType) == @symbol(filePointer)) |
6151 || (__INST(handleType) == @symbol(socketFilePointer)) |
6147 || (__INST(handleType) == @symbol(socketFilePointer)) |
6152 || (__INST(handleType) == @symbol(socketHandle)) |
6148 || (__INST(handleType) == @symbol(socketHandle)) |
6153 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6149 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6154 OBJ fp; |
6150 OBJ fp; |
6155 |
6151 |
6156 if (((fp = __INST(handle)) != nil) |
6152 if (((fp = __INST(handle)) != nil) |
6157 && (__INST(mode) != @symbol(readonly)) |
6153 && (__INST(mode) != @symbol(readonly)) |
6158 ) { |
6154 ) { |
6159 FILEPOINTER f = __FILEVal(fp); |
6155 FILEPOINTER f = __FILEVal(fp); |
6160 int _buffered = (__INST(buffered) == true); |
6156 int _buffered = (__INST(buffered) == true); |
6161 int cnt; |
6157 int cnt; |
6162 char buff[2]; |
6158 char buff[2]; |
6163 int nBytes = 1; |
6159 int nBytes = 1; |
6164 |
6160 |
6165 if (__INST(binary) != true) { |
6161 if (__INST(binary) != true) { |
6166 if (__isCharacter(aCharacter)) { |
6162 if (__isCharacter(aCharacter)) { |
6167 unsigned int codePoint = __intVal(__characterVal(aCharacter)); |
6163 unsigned int codePoint = __intVal(__characterVal(aCharacter)); |
6168 if (codePoint <= 0xFF) { |
6164 if (codePoint <= 0xFF) { |
6169 unsigned char c = codePoint; |
6165 unsigned char c = codePoint; |
6170 buff[0] = c; nBytes = 1; |
6166 buff[0] = c; nBytes = 1; |
6171 |
6167 |
6172 if (c == '\n') { |
6168 if (c == '\n') { |
6173 OBJ mode = __INST(eolMode); |
6169 OBJ mode = __INST(eolMode); |
6174 if (mode == @symbol(nl)) { |
6170 if (mode == @symbol(nl)) { |
6175 // no EOL translation |
6171 // no EOL translation |
6176 } else if (mode == nil) { |
6172 } else if (mode == nil) { |
6177 // no EOL translation |
6173 // no EOL translation |
6178 } else if (mode == @symbol(cr)) { |
6174 } else if (mode == @symbol(cr)) { |
6179 buff[0] = '\r'; |
6175 buff[0] = '\r'; |
6180 } else if (mode == @symbol(eot)) { |
6176 } else if (mode == @symbol(eot)) { |
6181 buff[0] = '\004'; |
6177 buff[0] = '\004'; |
6182 } else if (mode == @symbol(etx)) { |
6178 } else if (mode == @symbol(etx)) { |
6183 buff[0] = '\003'; |
6179 buff[0] = '\003'; |
6184 } else if (mode == @symbol(crlf)) { |
6180 } else if (mode == @symbol(crlf)) { |
6185 buff[0] = '\r'; |
6181 buff[0] = '\r'; |
6186 buff[1] = '\n'; |
6182 buff[1] = '\n'; |
6187 nBytes = 2; |
6183 nBytes = 2; |
6188 } |
6184 } |
6189 } |
6185 } |
6190 doWrite: |
6186 doWrite: |
6191 if (! f) { |
6187 if (! f) { |
6192 fprintf(stderr, "oops - fileHandle is NULL in nextPut:\n"); |
6188 fprintf(stderr, "oops - fileHandle is NULL in nextPut:\n"); |
6193 __INST(handle) = nil; |
6189 __INST(handle) = nil; |
6194 goto out; |
6190 goto out; |
6195 } |
6191 } |
6196 |
6192 |
6197 if (_buffered) { |
6193 if (_buffered) { |
6198 __WRITING__(f) |
6194 __WRITING__(f) |
6199 } |
6195 } |
6200 # ifdef __win32__ |
6196 # ifdef __win32__ |
6201 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6197 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6202 cnt = __win32_fwrite(buff, 1, nBytes, f); |
6198 cnt = __win32_fwrite(buff, 1, nBytes, f); |
6203 } else |
6199 } else |
6204 # endif |
6200 # endif |
6205 { |
6201 { |
6206 __WRITEBYTES__(cnt, f, buff, nBytes, _buffered, __INST(handleType)); |
6202 __WRITEBYTES__(cnt, f, buff, nBytes, _buffered, __INST(handleType)); |
6207 } |
6203 } |
6208 if (cnt == nBytes) { |
6204 if (cnt == nBytes) { |
6209 if (__isSmallInteger(__INST(position))) { |
6205 if (__isSmallInteger(__INST(position))) { |
6210 INT np = __intVal(__INST(position)) + nBytes; |
6206 INT np = __intVal(__INST(position)) + nBytes; |
6211 OBJ t; |
6207 OBJ t; |
6212 |
6208 |
6213 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6209 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6214 } else { |
6210 } else { |
6215 __INST(position) = nil; /* i.e. do not know */ |
6211 __INST(position) = nil; /* i.e. do not know */ |
6216 } |
6212 } |
6217 RETURN ( self ); |
6213 RETURN ( self ); |
6218 } |
6214 } |
6219 error = __mkSmallInteger(__threadErrno); |
6215 error = __mkSmallInteger(__threadErrno); |
6220 } |
6216 } |
6221 } |
6217 } |
6222 } else { |
6218 } else { |
6223 if (__isSmallInteger(aCharacter)) { |
6219 if (__isSmallInteger(aCharacter)) { |
6224 unsigned char c = __intVal(aCharacter); |
6220 unsigned char c = __intVal(aCharacter); |
6225 buff[0] = c; nBytes = 1; |
6221 buff[0] = c; nBytes = 1; |
6226 goto doWrite; |
6222 goto doWrite; |
6227 } |
6223 } |
6228 } |
6224 } |
6229 } |
6225 } |
6230 } |
6226 } |
6231 out: ; |
6227 out: ; |
6232 #endif /* not SCHTEAM */ |
6228 #endif /* not SCHTEAM */ |
6233 %}. |
6229 %}. |
6234 error notNil ifTrue:[ |
6230 error notNil ifTrue:[ |
6235 lastErrorNumber := error. |
6231 lastErrorNumber := error. |
6236 self writeError:error. |
6232 self writeError:error. |
6237 ^ self |
6233 ^ self |
6238 ]. |
6234 ]. |
6239 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
6235 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
6240 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
6236 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
6241 binary == true ifTrue:[ |
6237 binary == true ifTrue:[ |
6242 aCharacter isInteger ifFalse:[ |
6238 aCharacter isInteger ifFalse:[ |
6243 self argumentMustBeInteger. |
6239 self argumentMustBeInteger. |
6244 ^ self. |
6240 ^ self. |
6245 ]. |
6241 ]. |
6246 ] ifFalse:[ |
6242 ] ifFalse:[ |
6247 (aCharacter isCharacter not |
6243 (aCharacter isCharacter not |
6248 or:[aCharacter codePoint > 16rFF]) ifTrue:[ |
6244 or:[aCharacter codePoint > 16rFF]) ifTrue:[ |
6249 self argumentMustBeCharacter. |
6245 self argumentMustBeCharacter. |
6250 ^ self. |
6246 ^ self. |
6251 ]. |
6247 ]. |
6252 ]. |
6248 ]. |
6253 "/ migration support |
6249 "/ migration support |
6254 self |
6250 self |
6255 nextPutByte:aCharacter asInteger |
6251 nextPutByte:aCharacter asInteger |
6256 toFile:handle |
6252 toFile:handle |
6257 ! |
6253 ! |
6258 |
6254 |
6259 nextPutAll:aCollection |
6255 nextPutAll:aCollection |
6260 "write all elements of the argument, aCollection. |
6256 "write all elements of the argument, aCollection. |
6261 Reimplemented for speed when writing strings or byteArrays. |
6257 Reimplemented for speed when writing strings or byteArrays. |
6266 #ifdef __SCHTEAM__ |
6262 #ifdef __SCHTEAM__ |
6267 STObject handle = self.instVarAt(I_handle); |
6263 STObject handle = self.instVarAt(I_handle); |
6268 |
6264 |
6269 if ((handle != STObject.Nil) |
6265 if ((handle != STObject.Nil) |
6270 && (aCollection.isSTString())) { |
6266 && (aCollection.isSTString())) { |
6271 handle.writeCharacters( aCollection.asSTString().characters ); |
6267 handle.writeCharacters( aCollection.asSTString().characters ); |
6272 self.instVarAt_put(I_position, STObject.Nil); |
6268 self.instVarAt_put(I_position, STObject.Nil); |
6273 return __c__._RETURN_self(); |
6269 return __c__._RETURN_self(); |
6274 } |
6270 } |
6275 #else |
6271 #else |
6276 |
6272 |
6277 __INST(lastErrorNumber) = nil; |
6273 __INST(lastErrorNumber) = nil; |
6278 |
6274 |
6279 if ((__INST(handleType) == nil) |
6275 if ((__INST(handleType) == nil) |
6280 || (__INST(handleType) == @symbol(filePointer)) |
6276 || (__INST(handleType) == @symbol(filePointer)) |
6281 || (__INST(handleType) == @symbol(socketFilePointer)) |
6277 || (__INST(handleType) == @symbol(socketFilePointer)) |
6282 || (__INST(handleType) == @symbol(socketHandle)) |
6278 || (__INST(handleType) == @symbol(socketHandle)) |
6283 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6279 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6284 OBJ fp; |
6280 OBJ fp; |
6285 |
6281 |
6286 if (((fp = __INST(handle)) != nil) |
6282 if (((fp = __INST(handle)) != nil) |
6287 && (__INST(mode) != @symbol(readonly)) |
6283 && (__INST(mode) != @symbol(readonly)) |
6288 ) { |
6284 ) { |
6289 INT len, cnt; |
6285 INT len, cnt; |
6290 INT o_offs; |
6286 INT o_offs; |
6291 FILEPOINTER f = __FILEVal(fp); |
6287 FILEPOINTER f = __FILEVal(fp); |
6292 int _buffered = (__INST(buffered) == true); |
6288 int _buffered = (__INST(buffered) == true); |
6293 |
6289 |
6294 if (! f) { |
6290 if (! f) { |
6295 fprintf(stderr, "oops - fileHandle is NULL in nextPutAll:\n"); |
6291 fprintf(stderr, "oops - fileHandle is NULL in nextPutAll:\n"); |
6296 __INST(handle) = nil; |
6292 __INST(handle) = nil; |
6297 goto out; |
6293 goto out; |
6298 } |
6294 } |
6299 if (_buffered) { |
6295 if (_buffered) { |
6300 __WRITING__(f) |
6296 __WRITING__(f) |
6301 } |
6297 } |
6302 |
6298 |
6303 if (__isStringLike(aCollection)) { |
6299 if (__isStringLike(aCollection)) { |
6304 OBJ mode = __INST(eolMode); |
6300 OBJ mode = __INST(eolMode); |
6305 char *stringP = __stringVal(aCollection); |
6301 char *stringP = __stringVal(aCollection); |
6306 len = __stringSize(aCollection); |
6302 len = __stringSize(aCollection); |
6307 |
6303 |
6308 if (__INST(binary) != true |
6304 if (__INST(binary) != true |
6309 && ((mode == @symbol(cr)) |
6305 && ((mode == @symbol(cr)) |
6310 || (mode == @symbol(etx)) |
6306 || (mode == @symbol(etx)) |
6311 || (mode == @symbol(eot)) |
6307 || (mode == @symbol(eot)) |
6312 || (mode == @symbol(crlf))) |
6308 || (mode == @symbol(crlf))) |
6313 && memchr(stringP, '\n', len) != NULL) |
6309 && memchr(stringP, '\n', len) != NULL) |
6314 { |
6310 { |
6315 // there is a '\n' to be translated, replace it into a buffer |
6311 // there is a '\n' to be translated, replace it into a buffer |
6316 |
6312 |
6317 char *end; |
6313 char *end; |
6318 char sep[2]; |
6314 char sep[2]; |
6319 int sepLen = 1; |
6315 int sepLen = 1; |
6320 int bufLen; |
6316 int bufLen; |
6321 char *buf, *endBuf, *sp, *dp; |
6317 char *buf, *endBuf, *sp, *dp; |
6322 |
6318 |
6323 sep[0] = '\n'; |
6319 sep[0] = '\n'; |
6324 if (mode == @symbol(crlf)) { |
6320 if (mode == @symbol(crlf)) { |
6325 sep[0] = '\r'; sep[1] = '\n'; sepLen = 2; |
6321 sep[0] = '\r'; sep[1] = '\n'; sepLen = 2; |
6326 } else if (mode == @symbol(cr)) { |
6322 } else if (mode == @symbol(cr)) { |
6327 sep[0] = '\r'; |
6323 sep[0] = '\r'; |
6328 } else if (mode == @symbol(eot)) { |
6324 } else if (mode == @symbol(eot)) { |
6329 sep[0] = '\004'; |
6325 sep[0] = '\004'; |
6330 } else if (mode == @symbol(etx)) { |
6326 } else if (mode == @symbol(etx)) { |
6331 sep[0] = '\003'; |
6327 sep[0] = '\003'; |
6332 } |
6328 } |
6333 |
6329 |
6334 // estimate size of buffer - assume every 4th char is a separator |
6330 // estimate size of buffer - assume every 4th char is a separator |
6335 bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen); |
6331 bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen); |
6336 buf = (char *)malloc(bufLen); |
6332 buf = (char *)malloc(bufLen); |
6337 if (buf == NULL) { |
6333 if (buf == NULL) { |
6338 error = __mkSmallInteger(ENOMEM); |
6334 error = __mkSmallInteger(ENOMEM); |
6339 goto out; |
6335 goto out; |
6340 } |
6336 } |
6341 |
6337 |
6342 endBuf = buf + bufLen; |
6338 endBuf = buf + bufLen; |
6343 end = stringP + len; |
6339 end = stringP + len; |
6344 for (sp = stringP, dp = buf; sp < end; sp++) { |
6340 for (sp = stringP, dp = buf; sp < end; sp++) { |
6345 char c; |
6341 char c; |
6346 |
6342 |
6347 if ((dp+sepLen) >= endBuf) { |
6343 if ((dp+sepLen) >= endBuf) { |
6348 char *newBuf; |
6344 char *newBuf; |
6349 |
6345 |
6350 bufLen = bufLen * 2; |
6346 bufLen = bufLen * 2; |
6351 newBuf = (char *)realloc(buf, bufLen); |
6347 newBuf = (char *)realloc(buf, bufLen); |
6352 if (newBuf == NULL) { |
6348 if (newBuf == NULL) { |
6353 free(buf); |
6349 free(buf); |
6354 error = __mkSmallInteger(ENOMEM); |
6350 error = __mkSmallInteger(ENOMEM); |
6355 goto out; |
6351 goto out; |
6356 } |
6352 } |
6357 endBuf = newBuf + bufLen; |
6353 endBuf = newBuf + bufLen; |
6358 dp = newBuf + (dp-buf); |
6354 dp = newBuf + (dp-buf); |
6359 buf = newBuf; |
6355 buf = newBuf; |
6360 } |
6356 } |
6361 |
6357 |
6362 if ((c = *sp) != '\n') { |
6358 if ((c = *sp) != '\n') { |
6363 *dp++ = c; |
6359 *dp++ = c; |
6364 } else { |
6360 } else { |
6365 *dp++ = sep[0]; |
6361 *dp++ = sep[0]; |
6366 if (sepLen == 2) { |
6362 if (sepLen == 2) { |
6367 *dp++ = sep[1]; |
6363 *dp++ = sep[1]; |
6368 }; |
6364 }; |
6369 } |
6365 } |
6370 } |
6366 } |
6371 |
6367 |
6372 len = dp - buf; |
6368 len = dp - buf; |
6373 # ifdef __win32__ |
6369 # ifdef __win32__ |
6374 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6370 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6375 cnt = __win32_fwrite(buf, 1, len, f); |
6371 cnt = __win32_fwrite(buf, 1, len, f); |
6376 } else |
6372 } else |
6377 # endif |
6373 # endif |
6378 { |
6374 { |
6379 __WRITEBYTES__(cnt, f, buf, len, _buffered, __INST(handleType)); |
6375 __WRITEBYTES__(cnt, f, buf, len, _buffered, __INST(handleType)); |
6380 } |
6376 } |
6381 free(buf); |
6377 free(buf); |
6382 } else { // No EOL conversion needed |
6378 } else { // No EOL conversion needed |
6383 # ifdef __win32__ |
6379 # ifdef __win32__ |
6384 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6380 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6385 cnt = __win32_fwrite(stringP, 1, len, f); |
6381 cnt = __win32_fwrite(stringP, 1, len, f); |
6386 } else |
6382 } else |
6387 # endif |
6383 # endif |
6388 { |
6384 { |
6389 o_offs = stringP - (char *)__InstPtr(aCollection); |
6385 o_offs = stringP - (char *)__InstPtr(aCollection); |
6390 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType)); |
6386 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType)); |
6391 } |
6387 } |
6392 } |
6388 } |
6393 } else { // Not a String |
6389 } else { // Not a String |
6394 if (__INST(binary) == true) { |
6390 if (__INST(binary) == true) { |
6395 INT offs; |
6391 INT offs; |
6396 |
6392 |
6397 if (__isByteArrayLike(aCollection)) { |
6393 if (__isByteArrayLike(aCollection)) { |
6398 offs = 0; |
6394 offs = 0; |
6399 len = __byteArraySize(aCollection); |
6395 len = __byteArraySize(aCollection); |
6400 } else if (__isBytes(aCollection)) { |
6396 } else if (__isBytes(aCollection)) { |
6401 offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars)); |
6397 offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars)); |
6402 len = __byteArraySize(aCollection) - offs; |
6398 len = __byteArraySize(aCollection) - offs; |
6403 } else |
6399 } else |
6404 goto out; |
6400 goto out; |
6405 # ifdef __win32__ |
6401 # ifdef __win32__ |
6406 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6402 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6407 cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f); |
6403 cnt = __win32_fwrite(__stringVal(aCollection), 1, len, f); |
6408 } else |
6404 } else |
6409 # endif |
6405 # endif |
6410 { |
6406 { |
6411 o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element) - (char *)__InstPtr(aCollection); |
6407 o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element) - (char *)__InstPtr(aCollection); |
6412 o_offs += offs; |
6408 o_offs += offs; |
6413 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType)); |
6409 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs, len, _buffered, __INST(handleType)); |
6414 } |
6410 } |
6415 } else // Not binary mode |
6411 } else // Not binary mode |
6416 goto out; |
6412 goto out; |
6417 } |
6413 } |
6418 |
6414 |
6419 // Now check for errors |
6415 // Now check for errors |
6420 if (cnt == len) { |
6416 if (cnt == len) { |
6421 if (__isSmallInteger(__INST(position))) { |
6417 if (__isSmallInteger(__INST(position))) { |
6422 INT np = __intVal(__INST(position)) + len; |
6418 INT np = __intVal(__INST(position)) + len; |
6423 OBJ t; |
6419 OBJ t; |
6424 |
6420 |
6425 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6421 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6426 } else { |
6422 } else { |
6427 __INST(position) = nil; /* i.e. do not know */ |
6423 __INST(position) = nil; /* i.e. do not know */ |
6428 } |
6424 } |
6429 RETURN (self); |
6425 RETURN (self); |
6430 } |
6426 } |
6431 fprintf(stderr, "cnt=%"_ld_" len=%"_ld_"\n", (INT)cnt, (INT)len); |
6427 fprintf(stderr, "cnt=%"_ld_" len=%"_ld_"\n", (INT)cnt, (INT)len); |
6432 error = __mkSmallInteger(__threadErrno); |
6428 error = __mkSmallInteger(__threadErrno); |
6433 } |
6429 } |
6434 } |
6430 } |
6435 out: ; |
6431 out: ; |
6436 #endif /* not SCHTEAM */ |
6432 #endif /* not SCHTEAM */ |
6437 %}. |
6433 %}. |
6438 error notNil ifTrue:[ |
6434 error notNil ifTrue:[ |
6439 lastErrorNumber := error. |
6435 lastErrorNumber := error. |
6440 self writeError:error. |
6436 self writeError:error. |
6441 ^ self |
6437 ^ self |
6442 ]. |
6438 ]. |
6443 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
6439 handle isNil ifTrue:[self errorNotOpen. ^ self]. |
6444 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
6440 (mode == #readonly) ifTrue:[self errorReadOnly. ^ self]. |
6445 |
6441 |
6446 ^ super nextPutAll:aCollection |
6442 ^ super nextPutAll:aCollection |
6453 Answer the number of elements that were appended. |
6449 Answer the number of elements that were appended. |
6454 Buffer should be a byte collection. |
6450 Buffer should be a byte collection. |
6455 I don't know how to write non-bytes to an external stream, but let superclass handle this." |
6451 I don't know how to write non-bytes to an external stream, but let superclass handle this." |
6456 |
6452 |
6457 buffer isSingleByteCollection ifTrue:[ |
6453 buffer isSingleByteCollection ifTrue:[ |
6458 ^ self nextPutBytes:initialWriteCount from:buffer startingAt:initialOffset. |
6454 ^ self nextPutBytes:initialWriteCount from:buffer startingAt:initialOffset. |
6459 ]. |
6455 ]. |
6460 |
6456 |
6461 ^ super nextPutAll:initialWriteCount from:buffer startingAt:initialOffset |
6457 ^ super nextPutAll:initialWriteCount from:buffer startingAt:initialOffset |
6462 ! |
6458 ! |
6463 |
6459 |
6473 if ((__INST(handleType) == nil) |
6469 if ((__INST(handleType) == nil) |
6474 || (__INST(handleType) == @symbol(filePointer)) |
6470 || (__INST(handleType) == @symbol(filePointer)) |
6475 || (__INST(handleType) == @symbol(socketFilePointer)) |
6471 || (__INST(handleType) == @symbol(socketFilePointer)) |
6476 || (__INST(handleType) == @symbol(socketHandle)) |
6472 || (__INST(handleType) == @symbol(socketHandle)) |
6477 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6473 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6478 OBJ fp = __INST(handle); |
6474 OBJ fp = __INST(handle); |
6479 |
6475 |
6480 if ((fp != nil) |
6476 if ((fp != nil) |
6481 && (__INST(mode) != @symbol(readonly)) |
6477 && (__INST(mode) != @symbol(readonly)) |
6482 && __bothSmallInteger(start, stop) |
6478 && __bothSmallInteger(start, stop) |
6483 ) { |
6479 ) { |
6484 int _buffered = (__INST(buffered) == true); |
6480 int _buffered = (__INST(buffered) == true); |
6485 FILEPOINTER f = __FILEVal(fp); |
6481 FILEPOINTER f = __FILEVal(fp); |
6486 int offs, len, cnt; |
6482 int offs, len, cnt; |
6487 int iStart = __intVal(start); |
6483 int iStart = __intVal(start); |
6488 int iStop = __intVal(stop); |
6484 int iStop = __intVal(stop); |
6489 int o_offs; |
6485 int o_offs; |
6490 |
6486 |
6491 if (_buffered ) { |
6487 if (_buffered ) { |
6492 __WRITING__(f) |
6488 __WRITING__(f) |
6493 } |
6489 } |
6494 |
6490 |
6495 if ((iStart < 1) || (iStop < iStart)) { |
6491 if ((iStart < 1) || (iStop < iStart)) { |
6496 RETURN(self); |
6492 RETURN(self); |
6497 } |
6493 } |
6498 if (__isStringLike(aCollection)) { |
6494 if (__isStringLike(aCollection)) { |
6499 char *stringP; |
6495 char *stringP; |
6500 OBJ mode = __INST(eolMode); |
6496 OBJ mode = __INST(eolMode); |
6501 |
6497 |
6502 len = __stringSize(aCollection); |
6498 len = __stringSize(aCollection); |
6503 if (iStop > len) { |
6499 if (iStop > len) { |
6504 RETURN(self); |
6500 RETURN(self); |
6505 } |
6501 } |
6506 if (iStop > len) |
6502 if (iStop > len) |
6507 iStop = len; |
6503 iStop = len; |
6508 len = iStop - iStart + 1; |
6504 len = iStop - iStart + 1; |
6509 stringP = __stringVal(aCollection) + iStart - 1; |
6505 stringP = __stringVal(aCollection) + iStart - 1; |
6510 |
6506 |
6511 if (__INST(binary) != true |
6507 if (__INST(binary) != true |
6512 && ((mode == @symbol(cr)) |
6508 && ((mode == @symbol(cr)) |
6513 || (mode == @symbol(etx)) |
6509 || (mode == @symbol(etx)) |
6514 || (mode == @symbol(eot)) |
6510 || (mode == @symbol(eot)) |
6515 || (mode == @symbol(crlf))) |
6511 || (mode == @symbol(crlf))) |
6516 && memchr(stringP, '\n', len) != NULL) |
6512 && memchr(stringP, '\n', len) != NULL) |
6517 { |
6513 { |
6518 // see if there is a \n which needs to be translated, replace it |
6514 // see if there is a \n which needs to be translated, replace it |
6519 |
6515 |
6520 char *end = stringP + len; |
6516 char *end = stringP + len; |
6521 char sep[2]; |
6517 char sep[2]; |
6522 int sepLen = 1; |
6518 int sepLen = 1; |
6523 int bufLen; |
6519 int bufLen; |
6524 char *buf, *endBuf, *sp, *dp; |
6520 char *buf, *endBuf, *sp, *dp; |
6525 |
6521 |
6526 sep[0] = '\n'; |
6522 sep[0] = '\n'; |
6527 if (mode == @symbol(crlf)) { |
6523 if (mode == @symbol(crlf)) { |
6528 sep[0] = '\r'; sep[1] = '\n'; sepLen = 2; |
6524 sep[0] = '\r'; sep[1] = '\n'; sepLen = 2; |
6529 } else if (mode == @symbol(cr)) { |
6525 } else if (mode == @symbol(cr)) { |
6530 sep[0] = '\r'; |
6526 sep[0] = '\r'; |
6531 } else if (mode == @symbol(eot)) { |
6527 } else if (mode == @symbol(eot)) { |
6532 sep[0] = '\004'; |
6528 sep[0] = '\004'; |
6533 } else if (mode == @symbol(etx)) { |
6529 } else if (mode == @symbol(etx)) { |
6534 sep[0] = '\003'; |
6530 sep[0] = '\003'; |
6535 } |
6531 } |
6536 |
6532 |
6537 // estimate size of buffer - assume every 4th char is a separator |
6533 // estimate size of buffer - assume every 4th char is a separator |
6538 bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen); |
6534 bufLen = (sepLen == 1) ? len : (len + ((len/4) + 1) * sepLen); |
6539 buf = (char *)malloc(bufLen); |
6535 buf = (char *)malloc(bufLen); |
6540 if (buf == NULL) { |
6536 if (buf == NULL) { |
6541 error = __mkSmallInteger(ENOMEM); |
6537 error = __mkSmallInteger(ENOMEM); |
6542 goto out; |
6538 goto out; |
6543 } |
6539 } |
6544 |
6540 |
6545 endBuf = buf + bufLen; |
6541 endBuf = buf + bufLen; |
6546 |
6542 |
6547 for (sp = stringP, dp = buf; sp < end; sp++) { |
6543 for (sp = stringP, dp = buf; sp < end; sp++) { |
6548 char c; |
6544 char c; |
6549 |
6545 |
6550 if ((dp+sepLen) >= endBuf) { |
6546 if ((dp+sepLen) >= endBuf) { |
6551 char *newBuf; |
6547 char *newBuf; |
6552 |
6548 |
6553 bufLen = bufLen * 2; |
6549 bufLen = bufLen * 2; |
6554 newBuf = (char *)realloc(buf, bufLen); |
6550 newBuf = (char *)realloc(buf, bufLen); |
6555 if (newBuf == NULL) { |
6551 if (newBuf == NULL) { |
6556 free(buf); |
6552 free(buf); |
6557 error = __mkSmallInteger(ENOMEM); |
6553 error = __mkSmallInteger(ENOMEM); |
6558 goto out; |
6554 goto out; |
6559 } |
6555 } |
6560 endBuf = newBuf + bufLen; |
6556 endBuf = newBuf + bufLen; |
6561 dp = newBuf + (dp-buf); |
6557 dp = newBuf + (dp-buf); |
6562 buf = newBuf; |
6558 buf = newBuf; |
6563 } |
6559 } |
6564 |
6560 |
6565 if ((c = *sp) == '\n') { |
6561 if ((c = *sp) == '\n') { |
6566 *dp++ = sep[0]; |
6562 *dp++ = sep[0]; |
6567 if (sepLen == 2) { |
6563 if (sepLen == 2) { |
6568 *dp++ = sep[1]; |
6564 *dp++ = sep[1]; |
6569 }; |
6565 }; |
6570 } else { |
6566 } else { |
6571 *dp++ = c; |
6567 *dp++ = c; |
6572 } |
6568 } |
6573 } |
6569 } |
6574 |
6570 |
6575 len = dp - buf; |
6571 len = dp - buf; |
6576 #ifdef __win32__ |
6572 #ifdef __win32__ |
6577 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6573 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6578 cnt = __win32_fwrite(buf, 1, len, f); |
6574 cnt = __win32_fwrite(buf, 1, len, f); |
6579 } else |
6575 } else |
6580 #endif |
6576 #endif |
6581 { |
6577 { |
6582 __WRITEBYTES__(cnt, f, buf, len, _buffered, __INST(handleType)); |
6578 __WRITEBYTES__(cnt, f, buf, len, _buffered, __INST(handleType)); |
6583 } |
6579 } |
6584 free(buf); |
6580 free(buf); |
6585 } else { // No EOL conversion needed |
6581 } else { // No EOL conversion needed |
6586 #ifdef __win32__ |
6582 #ifdef __win32__ |
6587 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6583 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6588 cnt = __win32_fwrite(stringP, 1, len, f); |
6584 cnt = __win32_fwrite(stringP, 1, len, f); |
6589 } else |
6585 } else |
6590 #endif |
6586 #endif |
6591 { |
6587 { |
6592 o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection); |
6588 o_offs = (char *)__stringVal(aCollection)-(char *)__InstPtr(aCollection); |
6593 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+iStart-1, len, _buffered, __INST(handleType)); |
6589 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+iStart-1, len, _buffered, __INST(handleType)); |
6594 } |
6590 } |
6595 } |
6591 } |
6596 } else { // Not a string |
6592 } else { // Not a string |
6597 if (__INST(binary) == true) { |
6593 if (__INST(binary) == true) { |
6598 int offs; |
6594 int offs; |
6599 |
6595 |
6600 if (__isByteArrayLike(aCollection)) { |
6596 if (__isByteArrayLike(aCollection)) { |
6601 offs = 0; |
6597 offs = 0; |
6602 len = __byteArraySize(aCollection); |
6598 len = __byteArraySize(aCollection); |
6603 } else if (__isBytes(aCollection)) { |
6599 } else if (__isBytes(aCollection)) { |
6604 offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars)); |
6600 offs = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(aCollection))->c_ninstvars)); |
6605 len = __byteArraySize(aCollection) - offs; |
6601 len = __byteArraySize(aCollection) - offs; |
6606 } else |
6602 } else |
6607 goto out; |
6603 goto out; |
6608 |
6604 |
6609 if (iStop > len) { |
6605 if (iStop > len) { |
6610 RETURN(self); |
6606 RETURN(self); |
6611 } |
6607 } |
6612 if (iStop > len) |
6608 if (iStop > len) |
6613 iStop = len; |
6609 iStop = len; |
6614 len = iStop - iStart + 1; |
6610 len = iStop - iStart + 1; |
6615 offs += iStart - 1; |
6611 offs += iStart - 1; |
6616 #ifdef __win32__ |
6612 #ifdef __win32__ |
6617 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6613 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6618 cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f); |
6614 cnt = __win32_fwrite(__stringVal(aCollection)+iStart-1, 1, len, f); |
6619 } else |
6615 } else |
6620 #endif |
6616 #endif |
6621 { |
6617 { |
6622 o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element)-(char *)__InstPtr(aCollection); |
6618 o_offs = (char *)(__ByteArrayInstPtr(aCollection)->ba_element)-(char *)__InstPtr(aCollection); |
6623 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+offs, len, _buffered, __INST(handleType)); |
6619 __WRITEBYTES_OBJ__(cnt, f, aCollection, o_offs+offs, len, _buffered, __INST(handleType)); |
6624 } |
6620 } |
6625 } else |
6621 } else |
6626 goto out; |
6622 goto out; |
6627 } |
6623 } |
6628 if (cnt == len) { |
6624 if (cnt == len) { |
6629 if (__isSmallInteger(__INST(position))) { |
6625 if (__isSmallInteger(__INST(position))) { |
6630 INT np = __intVal(__INST(position)) + len; |
6626 INT np = __intVal(__INST(position)) + len; |
6631 OBJ t; |
6627 OBJ t; |
6632 |
6628 |
6633 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6629 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6634 } else { |
6630 } else { |
6635 __INST(position) = nil; /* i.e. do not know */ |
6631 __INST(position) = nil; /* i.e. do not know */ |
6636 } |
6632 } |
6637 RETURN (self); |
6633 RETURN (self); |
6638 } |
6634 } |
6639 error = __mkSmallInteger(__threadErrno); |
6635 error = __mkSmallInteger(__threadErrno); |
6640 } |
6636 } |
6641 } |
6637 } |
6642 out: ; |
6638 out: ; |
6643 %}. |
6639 %}. |
6644 error notNil ifTrue:[ |
6640 error notNil ifTrue:[ |
6645 lastErrorNumber := error. |
6641 lastErrorNumber := error. |
6646 self writeError:error. |
6642 self writeError:error. |
6647 ^ self |
6643 ^ self |
6648 ]. |
6644 ]. |
6649 ^ super nextPutAll:aCollection startingAt:start to:stop |
6645 ^ super nextPutAll:aCollection startingAt:start to:stop |
6650 ! |
6646 ! |
6651 |
6647 |
6652 nextPutAllUnicode:aString |
6648 nextPutAllUnicode:aString |
6653 "normal streams can not handle multi-byte characters, so convert them to utf8. |
6649 "normal streams can not handle multi-byte characters, so convert them to utf8. |
6654 This is needed, so that you can do ('something' asUnicode16String errorPrintCR)" |
6650 This is needed, so that you can do ('something' asUnicode16String errorPrintCR)" |
6655 |
6651 |
6656 aString do:[:eachCharacter| |
6652 aString do:[:eachCharacter| |
6657 self nextPutUtf8:eachCharacter. |
6653 self nextPutUtf8:eachCharacter. |
6658 ]. |
6654 ]. |
6659 |
6655 |
6660 " |
6656 " |
6661 'Bönnigheim' asUnicode16String errorPrintCR |
6657 'Bönnigheim' asUnicode16String errorPrintCR |
6662 " |
6658 " |
6663 ! |
6659 ! |
6664 |
6660 |
6665 nextPutBytes:count from:anObject startingAt:start |
6661 nextPutBytes:count from:anObject startingAt:start |
6666 "write count bytes from an object starting at index start. |
6662 "write count bytes from an object starting at index start. |
6669 (i.e. be a ByteArray, String, Float- or DoubleArray), |
6665 (i.e. be a ByteArray, String, Float- or DoubleArray), |
6670 or an externalBytes object (with known size). |
6666 or an externalBytes object (with known size). |
6671 |
6667 |
6672 Use with care - non object oriented i/o. |
6668 Use with care - non object oriented i/o. |
6673 Warning: |
6669 Warning: |
6674 in general, you cannot use this method to pass non-byte data to other |
6670 in general, you cannot use this method to pass non-byte data to other |
6675 architectures (unless you prepared the buffer with care), |
6671 architectures (unless you prepared the buffer with care), |
6676 since it does not care for byte order or float representation." |
6672 since it does not care for byte order or float representation." |
6677 |
6673 |
6678 |error| |
6674 |error| |
6679 |
6675 |
6680 %{ |
6676 %{ |
6681 #ifdef __SCHTEAM__ |
6677 #ifdef __SCHTEAM__ |
6682 byte[] bytes; |
6678 byte[] bytes; |
6683 STObject handle = self.instVarAt(I_handle); |
6679 STObject handle = self.instVarAt(I_handle); |
6684 |
6680 |
6685 if (anObject.isSTString()) { |
6681 if (anObject.isSTString()) { |
6686 char[] chars = anObject.asSTString().characters; |
6682 char[] chars = anObject.asSTString().characters; |
6687 handle.writeCharacters(chars, start.intValue()-1, count.intValue()); |
6683 handle.writeCharacters(chars, start.intValue()-1, count.intValue()); |
6688 self.instVarAt_put(I_position, STObject.Nil); |
6684 self.instVarAt_put(I_position, STObject.Nil); |
6689 return context._RETURN(count); |
6685 return context._RETURN(count); |
6690 } |
6686 } |
6691 if (anObject.isSymbol()) { |
6687 if (anObject.isSymbol()) { |
6692 java.lang.String chars = anObject.asSTSymbol().characters; |
6688 java.lang.String chars = anObject.asSTSymbol().characters; |
6693 handle.writeString(chars, start.intValue()-1, count.intValue()); |
6689 handle.writeString(chars, start.intValue()-1, count.intValue()); |
6694 self.instVarAt_put(I_position, STObject.Nil); |
6690 self.instVarAt_put(I_position, STObject.Nil); |
6695 return context._RETURN(count); |
6691 return context._RETURN(count); |
6696 } |
6692 } |
6697 #else |
6693 #else |
6698 int ret; |
6694 int ret; |
6699 int objSize, nInstBytes; |
6695 int objSize, nInstBytes; |
6700 char *extPtr; |
6696 char *extPtr; |
6704 if ((__INST(handleType) == nil) |
6700 if ((__INST(handleType) == nil) |
6705 || (__INST(handleType) == @symbol(filePointer)) |
6701 || (__INST(handleType) == @symbol(filePointer)) |
6706 || (__INST(handleType) == @symbol(socketFilePointer)) |
6702 || (__INST(handleType) == @symbol(socketFilePointer)) |
6707 || (__INST(handleType) == @symbol(socketHandle)) |
6703 || (__INST(handleType) == @symbol(socketHandle)) |
6708 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6704 || (__INST(handleType) == @symbol(pipeFilePointer))) { |
6709 if (((fp = __INST(handle)) != nil) |
6705 if (((fp = __INST(handle)) != nil) |
6710 && (__INST(mode) != @symbol(readonly)) |
6706 && (__INST(mode) != @symbol(readonly)) |
6711 && __bothSmallInteger(count, start) |
6707 && __bothSmallInteger(count, start) |
6712 ) { |
6708 ) { |
6713 int _buffered = (__INST(buffered) == true); |
6709 int _buffered = (__INST(buffered) == true); |
6714 FILEPOINTER f = __FILEVal(fp); |
6710 FILEPOINTER f = __FILEVal(fp); |
6715 int len = __intVal(count); |
6711 int len = __intVal(count); |
6716 int offs = __intVal(start) - 1; |
6712 int offs = __intVal(start) - 1; |
6717 |
6713 |
6718 if (__isExternalBytesLike(anObject)) { |
6714 if (__isExternalBytesLike(anObject)) { |
6719 OBJ sz; |
6715 OBJ sz; |
6720 |
6716 |
6721 nInstBytes = 0; |
6717 nInstBytes = 0; |
6722 extPtr = (char *)__externalBytesAddress(anObject); |
6718 extPtr = (char *)__externalBytesAddress(anObject); |
6723 if (extPtr == NULL) goto bad; |
6719 if (extPtr == NULL) goto bad; |
6724 sz = __externalBytesSize(anObject); |
6720 sz = __externalBytesSize(anObject); |
6725 if (__isSmallInteger(sz)) { |
6721 if (__isSmallInteger(sz)) { |
6726 objSize = __intVal(sz); |
6722 objSize = __intVal(sz); |
6727 } else { |
6723 } else { |
6728 objSize = 0; /* unknown */ |
6724 objSize = 0; /* unknown */ |
6729 } |
6725 } |
6730 } else { |
6726 } else { |
6731 OBJ oClass = __Class(anObject); |
6727 OBJ oClass = __Class(anObject); |
6732 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
6728 int nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
6733 |
6729 |
6734 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
6730 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
6735 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
6731 switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
6736 case BYTEARRAY: |
6732 case BYTEARRAY: |
6737 case WORDARRAY: |
6733 case WORDARRAY: |
6738 case LONGARRAY: |
6734 case LONGARRAY: |
6739 case SWORDARRAY: |
6735 case SWORDARRAY: |
6740 case SLONGARRAY: |
6736 case SLONGARRAY: |
6741 case FLOATARRAY: |
6737 case FLOATARRAY: |
6742 break; |
6738 break; |
6743 case DOUBLEARRAY: |
6739 case DOUBLEARRAY: |
6744 # ifdef __NEED_DOUBLE_ALIGN |
6740 # ifdef __NEED_DOUBLE_ALIGN |
6745 nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1); |
6741 nInstBytes = (nInstBytes-1+__DOUBLE_ALIGN) &~ (__DOUBLE_ALIGN-1); |
6746 # endif |
6742 # endif |
6747 break; |
6743 break; |
6748 case LONGLONGARRAY: |
6744 case LONGLONGARRAY: |
6749 case SLONGLONGARRAY: |
6745 case SLONGLONGARRAY: |
6750 # ifdef __NEED_LONGLONG_ALIGN |
6746 # ifdef __NEED_LONGLONG_ALIGN |
6751 nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1); |
6747 nInstBytes = (nInstBytes-1+__LONGLONG_ALIGN) &~ (__LONGLONG_ALIGN-1); |
6752 # endif |
6748 # endif |
6753 break; |
6749 break; |
6754 default: |
6750 default: |
6755 goto bad; |
6751 goto bad; |
6756 } |
6752 } |
6757 extPtr = (char *)0; |
6753 extPtr = (char *)0; |
6758 objSize = __Size(anObject) - nInstBytes; |
6754 objSize = __Size(anObject) - nInstBytes; |
6759 } |
6755 } |
6760 if ( (offs >= 0) && (len >= 0) && (objSize >= (len + offs)) ) { |
6756 if ( (offs >= 0) && (len >= 0) && (objSize >= (len + offs)) ) { |
6761 int cnt; |
6757 int cnt; |
6762 |
6758 |
6763 if (_buffered) { |
6759 if (_buffered) { |
6764 __WRITING__(f) |
6760 __WRITING__(f) |
6765 } |
6761 } |
6766 |
6762 |
6767 if (extPtr) { |
6763 if (extPtr) { |
6768 # ifdef __win32__ |
6764 # ifdef __win32__ |
6769 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6765 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6770 cnt = __win32_fwrite(extPtr+offs, 1, len, f); |
6766 cnt = __win32_fwrite(extPtr+offs, 1, len, f); |
6771 } else |
6767 } else |
6772 # endif |
6768 # endif |
6773 { |
6769 { |
6774 __WRITEBYTES__(cnt, f, extPtr+offs, len, _buffered, __INST(handleType)); |
6770 __WRITEBYTES__(cnt, f, extPtr+offs, len, _buffered, __INST(handleType)); |
6775 } |
6771 } |
6776 } else { |
6772 } else { |
6777 /* |
6773 /* |
6778 * on interrupt, anObject may be moved to another location. |
6774 * on interrupt, anObject may be moved to another location. |
6779 * So we pass anObject, and the offset to the __WRITEBYTES_OBJ__ macro. |
6775 * So we pass anObject, and the offset to the __WRITEBYTES_OBJ__ macro. |
6780 */ |
6776 */ |
6781 offs += nInstBytes; |
6777 offs += nInstBytes; |
6782 # ifdef __win32__ |
6778 # ifdef __win32__ |
6783 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6779 if ((f == __win32_stdout()) || (f == __win32_stderr())) { |
6784 cnt = __win32_fwrite((char *)anObject+offs, 1, len, f); |
6780 cnt = __win32_fwrite((char *)anObject+offs, 1, len, f); |
6785 } else |
6781 } else |
6786 # endif |
6782 # endif |
6787 { |
6783 { |
6788 __WRITEBYTES_OBJ__(cnt, f, anObject, offs, len, _buffered, __INST(handleType)); |
6784 __WRITEBYTES_OBJ__(cnt, f, anObject, offs, len, _buffered, __INST(handleType)); |
6789 } |
6785 } |
6790 } |
6786 } |
6791 |
6787 |
6792 if (cnt >= 0) { |
6788 if (cnt >= 0) { |
6793 if (__isSmallInteger(__INST(position))) { |
6789 if (__isSmallInteger(__INST(position))) { |
6794 INT np = __intVal(__INST(position)) + cnt; |
6790 INT np = __intVal(__INST(position)) + cnt; |
6795 OBJ t; |
6791 OBJ t; |
6796 |
6792 |
6797 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6793 t = __MKINT(np); __INST(position) = t; __STORE(self, t); |
6798 } else { |
6794 } else { |
6799 __INST(position) = nil; /* i.e. do not know */ |
6795 __INST(position) = nil; /* i.e. do not know */ |
6800 } |
6796 } |
6801 RETURN ( __mkSmallInteger(cnt) ); |
6797 RETURN ( __mkSmallInteger(cnt) ); |
6802 } else /* cnt < 0 */ { |
6798 } else /* cnt < 0 */ { |
6803 if ( |
6799 if ( |
6804 # ifdef EWOULDBLOCK |
6800 # ifdef EWOULDBLOCK |
6805 (__threadErrno == EWOULDBLOCK) || |
6801 (__threadErrno == EWOULDBLOCK) || |
6806 # endif |
6802 # endif |
6807 (__threadErrno == EAGAIN) |
6803 (__threadErrno == EAGAIN) |
6808 ) { |
6804 ) { |
6809 RETURN ( __mkSmallInteger(0) ); |
6805 RETURN ( __mkSmallInteger(0) ); |
6810 } |
6806 } |
6811 __INST(position) = nil; /* i.e. do not know */ |
6807 __INST(position) = nil; /* i.e. do not know */ |
6812 error = __mkSmallInteger(__threadErrno); |
6808 error = __mkSmallInteger(__threadErrno); |
6813 } |
6809 } |
6814 } |
6810 } |
6815 } |
6811 } |
6816 } |
6812 } |
6817 bad: ; |
6813 bad: ; |
6818 #endif /* not SCHTEAM */ |
6814 #endif /* not SCHTEAM */ |
6819 %}. |
6815 %}. |
6820 error notNil ifTrue:[ |
6816 error notNil ifTrue:[ |
6821 lastErrorNumber := error. |
6817 lastErrorNumber := error. |
6822 self writeError:error. |
6818 self writeError:error. |
6823 ^ 0 |
6819 ^ 0 |
6824 ]. |
6820 ]. |
6825 handle isNil ifTrue:[self errorNotOpen. ^ 0]. |
6821 handle isNil ifTrue:[self errorNotOpen. ^ 0]. |
6826 (mode == #readonly) ifTrue:[self errorReadOnly. ^ 0]. |
6822 (mode == #readonly) ifTrue:[self errorReadOnly. ^ 0]. |
6827 self primitiveFailed. |
6823 self primitiveFailed. |
6828 ^ 0. |
6824 ^ 0. |