89 For streams sitting on some communication channel (i.e. Pipes and Sockets) you should |
92 For streams sitting on some communication channel (i.e. Pipes and Sockets) you should |
90 reestablish the stream upon image restart (make someone dependent on ObjectMemory). |
93 reestablish the stream upon image restart (make someone dependent on ObjectMemory). |
91 |
94 |
92 Instance variables: |
95 Instance variables: |
93 |
96 |
94 filePointer <Integer> the unix FILE*; somehow mapped to an integer |
97 filePointer <Integer> the unix FILE*; somehow mapped to an integer |
95 (notice: not the fd) |
98 (notice: not the fd) |
96 mode <Symbol> #readwrite, #readonly or #writeonly |
99 mode <Symbol> #readwrite, #readonly or #writeonly |
97 buffered <Boolean> true, if buffered (i.e. collects characters - does |
100 buffered <Boolean> true, if buffered (i.e. collects characters - does |
98 not output immediately) |
101 not output immediately) |
99 binary <Boolean> true if in binary mode (reads bytes instead of chars) |
102 binary <Boolean> true if in binary mode (reads bytes instead of chars) |
100 useCRLF <Boolean> true, if lines should be terminated with crlf instead |
103 useCRLF <Boolean> true, if lines should be terminated with crlf instead |
101 of lf. (i.e. if file is an MSDOS-type file) |
104 of lf. (i.e. if file is an MSDOS-type file) |
102 hitEOF <Boolean> true, if EOF was reached |
105 hitEOF <Boolean> true, if EOF was reached |
103 |
106 |
|
107 lastErrorNumber <Integer> the value of errno (only valid right after the error - |
|
108 updated with next i/o operation) |
104 |
109 |
105 Class variables: |
110 Class variables: |
106 Lobby <Registry> keeps track of used ext-streams (to free up FILE*'s) |
111 Lobby <Registry> keeps track of used ext-streams (to free up FILE*'s) |
107 |
112 |
108 LastErrorNumber <Integer> the value of errno (only valid right after the error - |
113 StreamErrorSignal <Signal> parent of all stream errors |
109 updated with next i/o operation) |
114 ReadErrorSignal <Signal> raised on read errors |
110 |
115 WriteErrorSignal <Signal> raised on write errors |
111 Question: should lastErrorNumber be kept instance-specific ? |
116 InvalidReadSignal <Signal> raised on read from writeonly stream |
|
117 InvalidWriteSignal <Signal> raised on write to readonly stream |
|
118 InvalidModeSignal <Signal> raised on text I/O with binary-stream |
|
119 or binary I/O with text-stream |
|
120 StreamNotOpenSignal <Signal> raised on I/O with non-open stream |
|
121 |
|
122 Additional notes: |
|
123 This class is implemented using the underlying stdio-c library package, which |
|
124 has both advantages and disadvantages: since it is portable (posix defined), porting |
|
125 ST/X to non-Unix machines is simplified. The disadvantage is that the stdio library |
|
126 has big problems handling unbounded Streams, since the EOF handling in stdio is |
|
127 not prepared for data to arrive after EOF has been reached - time will show, if we need |
|
128 a complete rewrite for UnboundedStream ... |
112 " |
129 " |
113 ! ! |
130 ! ! |
114 |
131 |
115 !ExternalStream class methodsFor:'initialization'! |
132 !ExternalStream class methodsFor:'initialization'! |
116 |
133 |
117 initialize |
134 initialize |
|
135 StreamErrorSignal isNil ifTrue:[ |
|
136 super initialize. |
|
137 |
|
138 StreamErrorSignal := Object errorSignal newSignalMayProceed:false. |
|
139 StreamErrorSignal nameClass:self message:#streamErrorSignal. |
|
140 StreamErrorSignal notifierString:'I/O error'. |
|
141 |
|
142 ReadErrorSignal := StreamErrorSignal newSignalMayProceed:false. |
|
143 ReadErrorSignal nameClass:self message:#readErrorSignal. |
|
144 ReadErrorSignal notifierString:'read error'. |
|
145 |
|
146 WriteErrorSignal := StreamErrorSignal newSignalMayProceed:false. |
|
147 WriteErrorSignal nameClass:self message:#writeErrorSignal. |
|
148 WriteErrorSignal notifierString:'write error'. |
|
149 |
|
150 InvalidReadSignal := ReadErrorSignal newSignalMayProceed:false. |
|
151 InvalidReadSignal nameClass:self message:#invalidReadSignal. |
|
152 InvalidReadSignal notifierString:'write error'. |
|
153 |
|
154 InvalidWriteSignal := WriteErrorSignal newSignalMayProceed:false. |
|
155 InvalidWriteSignal nameClass:self message:#invalidWriteSignal. |
|
156 InvalidWriteSignal notifierString:'write error'. |
|
157 |
|
158 InvalidModeSignal := StreamErrorSignal newSignalMayProceed:false. |
|
159 InvalidModeSignal nameClass:self message:#invalidModeSignal. |
|
160 InvalidModeSignal notifierString:'binary/text mode mismatch'. |
|
161 |
|
162 StreamNotOpenSignal := StreamErrorSignal newSignalMayProceed:false. |
|
163 StreamNotOpenSignal nameClass:self message:#streamNotOpenSignal. |
|
164 StreamNotOpenSignal notifierString:'stream is not open'. |
|
165 ]. |
|
166 |
118 Lobby isNil ifTrue:[ |
167 Lobby isNil ifTrue:[ |
119 Lobby := Registry new. |
168 Lobby := Registry new. |
120 |
169 |
121 "want to get informed when returning from snapshot" |
170 "want to get informed when returning from snapshot" |
122 ObjectMemory addDependent:self |
171 ObjectMemory addDependent:self |
123 ] |
172 ] |
124 ! |
173 ! |
125 |
174 |
126 reOpenFiles |
175 reOpenFiles |
127 "reopen all files (if possible) after a snapShot load" |
176 "reopen all files (if possible) after a snapShot load" |
128 |
177 |
129 Lobby contentsDo:[:aFileStream | |
178 Lobby contentsDo:[:aFileStream | |
130 aFileStream reOpen |
179 aFileStream reOpen |
131 ] |
180 ] |
132 ! |
181 ! |
133 |
182 |
134 update:something |
183 update:something |
135 "have to reopen files when returning from snapshot" |
184 "have to reopen files when returning from snapshot" |
136 |
185 |
137 something == #returnFromSnapshot ifTrue:[ |
186 something == #returnFromSnapshot ifTrue:[ |
138 self reOpenFiles |
187 self reOpenFiles |
139 ] |
188 ] |
|
189 ! ! |
|
190 |
|
191 !ExternalStream class methodsFor:'signal access '! |
|
192 |
|
193 streamErrorSignal |
|
194 "return the parent of all stream errors; |
|
195 handling this one also handles all other errors. |
|
196 Also, this one is raised for errors not related to read/write |
|
197 operations, such as failed ioctls" |
|
198 |
|
199 ^ StreamErrorSignal |
|
200 ! |
|
201 |
|
202 readErrorSignal |
|
203 "return the signal raised on read errors" |
|
204 |
|
205 ^ ReadErrorSignal |
|
206 ! |
|
207 |
|
208 writeErrorSignal |
|
209 "return the signal raised on write errors" |
|
210 |
|
211 ^ WriteErrorSignal |
|
212 ! |
|
213 |
|
214 invalidReadSignal |
|
215 "return the signal raised when reading from writeonly streams" |
|
216 |
|
217 ^ InvalidReadSignal |
|
218 ! |
|
219 |
|
220 invalidWriteSignal |
|
221 "return the signal raised when writing to readonly streams" |
|
222 |
|
223 ^ InvalidWriteSignal |
|
224 ! |
|
225 |
|
226 invalidModeSignal |
|
227 "return the signal raised when doing text-I/O with a binary stream |
|
228 or binary-I/O with a text stream" |
|
229 |
|
230 ^ InvalidModeSignal |
|
231 ! |
|
232 |
|
233 streamNotOpenSignal |
|
234 "return the signal raised on I/O with closed streams" |
|
235 |
|
236 ^ StreamNotOpenSignal |
140 ! ! |
237 ! ! |
141 |
238 |
142 !ExternalStream class methodsFor:'instance creation'! |
239 !ExternalStream class methodsFor:'instance creation'! |
143 |
240 |
144 new |
241 new |
201 cannot reopen here since I am abstract and have no device knowledge" |
314 cannot reopen here since I am abstract and have no device knowledge" |
202 |
315 |
203 self class name errorPrint. ': cannot reOpen stream - stream closed' errorPrintNewline. |
316 self class name errorPrint. ': cannot reOpen stream - stream closed' errorPrintNewline. |
204 filePointer := nil. |
317 filePointer := nil. |
205 Lobby unregister:self. |
318 Lobby unregister:self. |
|
319 ! |
|
320 |
|
321 setLastError:aNumber |
|
322 lastErrorNumber := aNumber |
206 ! ! |
323 ! ! |
207 |
324 |
208 !ExternalStream methodsFor:'error handling'! |
325 !ExternalStream methodsFor:'error handling'! |
209 |
326 |
210 lastErrorNumber |
327 lastErrorNumber |
211 "return the last error" |
328 "return the last error" |
212 |
329 |
213 ^ LastErrorNumber |
330 ^ lastErrorNumber |
214 ! |
331 ! |
215 |
332 |
216 lastErrorString |
333 lastErrorString |
217 "return a message string describing the last error" |
334 "return a message string describing the last error" |
218 |
335 |
219 ^ self class lastErrorString |
336 (lastErrorNumber isNil or:[lastErrorNumber == 0]) ifTrue:[ |
|
337 ^ 'I/O error' |
|
338 ]. |
|
339 ^ OperatingSystem errorTextForNumber:lastErrorNumber |
220 ! |
340 ! |
221 |
341 |
222 errorNotOpen |
342 errorNotOpen |
223 "report an error, that the stream has not been opened" |
343 "report an error, that the stream has not been opened" |
224 |
344 |
225 ^ self error:(self class name , ' not open') |
345 ^ StreamNotOpenSignal |
|
346 raiseRequestWith:self |
|
347 errorString:(self class name , ' not open') |
226 ! |
348 ! |
227 |
349 |
228 errorReadOnly |
350 errorReadOnly |
229 "report an error, that the stream is a readOnly stream" |
351 "report an error, that the stream is a readOnly stream" |
230 |
352 |
231 ^ self error:(self class name , ' is readonly') |
353 ^ InvalidWriteSignal |
|
354 raiseRequestWith:self |
|
355 errorString:(self class name , ' is readonly') |
232 ! |
356 ! |
233 |
357 |
234 errorWriteOnly |
358 errorWriteOnly |
235 "report an error, that the stream is a writeOnly stream" |
359 "report an error, that the stream is a writeOnly stream" |
236 |
360 |
237 ^ self error:(self class name , ' is writeonly') |
361 ^ InvalidReadSignal |
|
362 raiseRequestWith:self |
|
363 errorString:(self class name , ' is writeonly') |
238 ! |
364 ! |
239 |
365 |
240 errorNotBinary |
366 errorNotBinary |
241 "report an error, that the stream is not in binary mode" |
367 "report an error, that the stream is not in binary mode" |
242 |
368 |
243 ^ self error:(self class name , ' is not in binary mode') |
369 ^ InvalidModeSignal |
|
370 raiseRequestWith:self |
|
371 errorString:(self class name , ' is not in binary mode') |
244 ! |
372 ! |
245 |
373 |
246 errorBinary |
374 errorBinary |
247 "report an error, that the stream is in binary mode" |
375 "report an error, that the stream is in binary mode" |
248 |
376 |
249 ^ self error:(self class name , ' is in binary mode') |
377 ^ InvalidModeSignal |
|
378 raiseRequestWith:self |
|
379 errorString:(self class name , ' is in binary mode') |
250 ! |
380 ! |
251 |
381 |
252 errorNotBuffered |
382 errorNotBuffered |
253 "report an error, that the stream is not in buffered mode" |
383 "report an error, that the stream is not in buffered mode" |
254 |
384 |
255 ^ self error:(self class name , ' is unbuffered - operation not allowed') |
385 ^ StreamErrorSignal |
|
386 raiseRequestWith:self |
|
387 errorString:(self class name , ' is unbuffered - operation not allowed') |
|
388 ! |
|
389 |
|
390 ioError |
|
391 "report an error, that some I/O error occured" |
|
392 |
|
393 ^ StreamErrorSignal |
|
394 raiseRequestWith:self |
|
395 errorString:('I/O error: ' , self lastErrorString) |
|
396 ! |
|
397 |
|
398 readError |
|
399 "report an error, that some read error occured" |
|
400 |
|
401 ^ ReadErrorSignal |
|
402 raiseRequestWith:self |
|
403 errorString:('read error: ' , self lastErrorString) |
|
404 ! |
|
405 |
|
406 writeError |
|
407 "report an error, that some write error occured" |
|
408 |
|
409 ^ WriteErrorSignal |
|
410 raiseRequestWith:self |
|
411 errorString:('write error: ' , self lastErrorString) |
256 ! |
412 ! |
257 |
413 |
258 argumentMustBeInteger |
414 argumentMustBeInteger |
259 "report an error, that the argument must be an integer" |
415 "report an error, that the argument must be an integer" |
260 |
416 |
480 FILE *f; |
651 FILE *f; |
481 int ret, ioNum, ioArg; |
652 int ret, ioNum, ioArg; |
482 extern int _immediateInterrupt; |
653 extern int _immediateInterrupt; |
483 extern errno; |
654 extern errno; |
484 |
655 |
|
656 _INST(lastErrorNumber) = nil; |
485 if (_INST(filePointer) != nil) { |
657 if (_INST(filePointer) != nil) { |
486 if (_isSmallInteger(ioctlNumber)) { |
658 if (_isSmallInteger(ioctlNumber)) { |
487 ioNum = _intVal(ioctlNumber); |
659 ioNum = _intVal(ioctlNumber); |
488 f = MKFD(_INST(filePointer)); |
660 f = MKFD(_INST(filePointer)); |
489 |
661 |
490 _immediateInterrupt = 1; |
662 _immediateInterrupt = 1; |
491 do { |
663 do { |
492 ret = ioctl(fileno(f), ioNum); |
664 ret = ioctl(fileno(f), ioNum); |
493 } while ((ret < 0) && (errno == EINTR)); |
665 } while ((ret < 0) && (errno == EINTR)); |
494 _immediateInterrupt = 0; |
666 _immediateInterrupt = 0; |
495 |
667 |
496 if (ret >= 0) { |
668 if (ret >= 0) { |
497 RETURN ( _MKSMALLINT(ret) ); |
669 RETURN ( _MKSMALLINT(ret) ); |
498 } |
670 } |
499 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
671 _INST(position) = nil; |
500 RETURN ( nil ); |
672 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
501 } |
673 } |
502 } |
674 } |
503 %} |
675 %}. |
504 . |
676 lastErrorNumber notNil ifTrue:[^ self ioError]. |
505 filePointer isNil ifTrue:[^ self errorNotOpen]. |
677 filePointer isNil ifTrue:[^ self errorNotOpen]. |
506 self primitiveFailed |
678 " |
|
679 ioctl-number is not an integer |
|
680 " |
|
681 ^ self primitiveFailed |
507 ! |
682 ! |
508 |
683 |
509 ioctl:ioctlNumber with:arg |
684 ioctl:ioctlNumber with:arg |
510 "to provide a simple ioctl facility - an ioctl is performed |
685 "to provide a simple ioctl facility - an ioctl is performed |
511 on the underlying file; the argument is passed as argument. |
686 on the underlying file; the argument is passed as argument. |
512 If the argument is a number, its directly passed; if its a |
687 If the argument is a number, its directly passed; if its a |
513 kind of ByteArray (ByteArray, String or Structure) a pointer to |
688 kind of ByteArray (ByteArray, String or Structure) a pointer to |
514 the data is passed. This allows performing most ioctls - however, |
689 the data is passed. This allows performing most ioctls - however, |
515 it might be tricky to setup the buffer." |
690 it might be tricky to setup the buffer." |
516 |
691 |
517 |isStructure| |
692 %{ /* NOCONTEXT */ |
518 |
|
519 isStructure := arg isKindOf:ByteArray. |
|
520 %{ |
|
521 FILE *f; |
693 FILE *f; |
522 int ret, ioNum; |
694 int ret, ioNum; |
523 extern int _immediateInterrupt; |
695 extern int _immediateInterrupt; |
524 extern errno; |
696 extern errno; |
525 |
697 |
|
698 _INST(lastErrorNumber) = nil; |
526 if (_INST(filePointer) != nil) { |
699 if (_INST(filePointer) != nil) { |
527 if (_isSmallInteger(ioctlNumber) |
700 if (_isSmallInteger(ioctlNumber) |
528 && (_isSmallInteger(arg) || (isStructure == true))) { |
701 && (_isSmallInteger(arg) || __isBytes(arg))) { |
529 f = MKFD(_INST(filePointer)); |
702 f = MKFD(_INST(filePointer)); |
530 ioNum = _intVal(ioctlNumber); |
703 ioNum = _intVal(ioctlNumber); |
531 |
704 |
532 _immediateInterrupt = 1; |
705 _immediateInterrupt = 1; |
533 do { |
706 do { |
534 if (isStructure == true) { |
707 if (_isSmallInteger(arg)) { |
535 ret = ioctl(fileno(f), ioNum, _ByteArrayInstPtr(arg)->ba_element); |
708 ret = ioctl(fileno(f), ioNum, _intVal(arg)); |
536 } else { |
709 } else { |
537 ret = ioctl(fileno(f), ioNum, _intVal(arg)); |
710 ret = ioctl(fileno(f), ioNum, _ByteArrayInstPtr(arg)->ba_element); |
538 } |
711 } |
539 } while ((ret < 0) && (errno == EINTR)); |
712 } while ((ret < 0) && (errno == EINTR)); |
540 _immediateInterrupt = 0; |
713 _immediateInterrupt = 0; |
541 |
714 |
542 if (ret >= 0) { |
715 if (ret >= 0) { |
543 RETURN ( _MKSMALLINT(ret) ); |
716 RETURN ( _MKSMALLINT(ret) ); |
544 } |
717 } |
545 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
718 _INST(position) = nil; |
546 RETURN ( nil ); |
719 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
547 } |
720 } |
548 } |
721 } |
549 %} |
722 %}. |
550 . |
723 lastErrorNumber notNil ifTrue:[^ self ioError]. |
551 filePointer isNil ifTrue:[^ self errorNotOpen]. |
724 filePointer isNil ifTrue:[^ self errorNotOpen]. |
552 self primitiveFailed |
725 " |
|
726 ioctl-number is not an integer or argument is not byteArray-like |
|
727 " |
|
728 ^ self primitiveFailed |
553 ! ! |
729 ! ! |
554 |
730 |
555 !ExternalStream methodsFor:'non homogenous reading'! |
731 !ExternalStream methodsFor:'non homogenous reading'! |
556 |
732 |
557 nextByte |
733 nextByte |
656 extern errno; |
839 extern errno; |
657 OBJ pos; |
840 OBJ pos; |
658 extern int _immediateInterrupt; |
841 extern int _immediateInterrupt; |
659 OBJ oClass; |
842 OBJ oClass; |
660 |
843 |
661 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
844 _INST(lastErrorNumber) = nil; |
662 if (_isSmallInteger(count) && _isSmallInteger(start)) { |
845 if ((_INST(filePointer) != nil) |
663 oClass = _Class(anObject); |
846 && (_INST(mode) != @symbol(writeonly))) { |
664 switch (_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
847 if (_isSmallInteger(count) && _isSmallInteger(start)) { |
665 case BYTEARRAY: |
848 oClass = _Class(anObject); |
666 case WORDARRAY: |
849 switch (_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
667 case LONGARRAY: |
850 case BYTEARRAY: |
668 case FLOATARRAY: |
851 case WORDARRAY: |
669 case DOUBLEARRAY: |
852 case LONGARRAY: |
670 break; |
853 case FLOATARRAY: |
671 default: |
854 case DOUBLEARRAY: |
672 goto bad; |
855 break; |
673 } |
856 default: |
674 cnt = _intVal(count); |
857 goto bad; |
675 offs = _intVal(start) - 1; |
858 } |
676 f = MKFD(_INST(filePointer)); |
859 cnt = _intVal(count); |
677 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
860 offs = _intVal(start) - 1; |
678 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
861 f = MKFD(_INST(filePointer)); |
679 objSize = _Size(anObject) - nInstBytes; |
862 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
680 if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) { |
863 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
681 cp = (char *)_InstPtr(anObject) + nInstBytes + offs; |
864 objSize = _Size(anObject) - nInstBytes; |
682 |
865 if ((offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs))) { |
683 _immediateInterrupt = 1; |
866 cp = (char *)_InstPtr(anObject) + nInstBytes + offs; |
684 do { |
867 |
685 if (_INST(buffered) == false) { |
868 _immediateInterrupt = 1; |
686 cnt = read(fileno(f), cp, cnt); |
869 do { |
687 } else { |
870 if (_INST(buffered) == false) { |
688 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
871 cnt = read(fileno(f), cp, cnt); |
689 _INST(didWrite) = false; |
872 } else { |
690 fseek(f, 0L, 1); /* needed in stdio */ |
873 if ((_INST(didWrite) != false) |
691 } |
874 && (_INST(mode) == @symbol(readwrite))) { |
692 cnt = fread(cp, 1, cnt, f); |
875 _INST(didWrite) = false; |
693 } |
876 fseek(f, 0L, 1); /* needed in stdio */ |
694 } while ((cnt < 0) && (errno == EINTR)); |
877 } |
695 _immediateInterrupt = 0; |
878 cnt = fread(cp, 1, cnt, f); |
696 |
879 } |
697 if (cnt >= 0) { |
880 } while ((cnt < 0) && (errno == EINTR)); |
698 if (cnt == 0) |
881 _immediateInterrupt = 0; |
699 _INST(hitEOF) = true; |
882 |
700 else { |
883 if (cnt >= 0) { |
701 pos = _INST(position); |
884 if (cnt == 0) |
702 if (pos != nil) |
885 _INST(hitEOF) = true; |
703 _INST(position) = _MKSMALLINT(_intVal(pos) + cnt); |
886 else { |
704 } |
887 pos = _INST(position); |
705 RETURN ( _MKSMALLINT(cnt) ); |
888 if (pos != nil) |
706 } |
889 _INST(position) = _MKSMALLINT(_intVal(pos) + cnt); |
707 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
890 } |
708 RETURN ( nil ); |
891 RETURN (_MKSMALLINT(cnt)); |
709 } |
892 } |
710 } |
893 _INST(position) = nil; |
|
894 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
895 } |
|
896 } |
711 } |
897 } |
712 bad: ; |
898 bad: ; |
713 %} |
899 %}. |
714 . |
900 lastErrorNumber notNil ifTrue:[^ self readError]. |
715 filePointer isNil ifTrue:[^ self errorNotOpen]. |
901 filePointer isNil ifTrue:[^ self errorNotOpen]. |
716 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
902 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
717 self primitiveFailed |
903 " |
718 ! |
904 count not integer or arg not bit-like (String, ByteArray etc) |
719 |
905 " |
720 nextWord |
906 ^ self primitiveFailed |
721 "in text-mode: |
907 ! |
722 read the next word (i.e. up to non letter-or-digit). |
908 |
723 return a string containing those characters. |
909 nextShortMSB:msbFlag |
724 in binary-mode: |
910 "Read two bytes and return the value as a 16-bit signed Integer. |
725 read two bytes (msb-first) and return the value as a 16-bit unsigned Integer |
911 If msbFlag is true, value is read with most-significant byte first, |
726 (for compatibility with other smalltalks)" |
912 otherwise least-significant byte comes first. |
|
913 A nil is returned if EOF is reached (also when EOF is hit after the first byte). |
|
914 Works in both binary and text modes." |
727 |
915 |
728 %{ /* NOCONTEXT */ |
916 %{ /* NOCONTEXT */ |
729 extern int _immediateInterrupt; |
917 extern int _immediateInterrupt; |
730 int _buffered; |
918 |
731 |
919 _INST(lastErrorNumber) = nil; |
732 _buffered = (_INST(buffered) == true); |
920 if ((_INST(filePointer) != nil) |
733 /* |
921 && (_INST(mode) != @symbol(writeonly))) { |
734 * binary mode |
922 FILE *f; |
735 */ |
923 int first, second, err; |
736 if (_INST(binary) == true) { |
924 short value; |
737 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
925 |
738 FILE *f; |
926 f = MKFD(_INST(filePointer)); |
739 unsigned char hi, low; |
927 |
740 int cnt; |
928 _immediateInterrupt = 1; |
741 OBJ pos; |
929 if ((_INST(didWrite) != false) |
742 |
930 && (_INST(mode) == @symbol(readwrite))) { |
743 f = MKFD(_INST(filePointer)); |
931 _INST(didWrite) = false; |
744 |
932 fseek(f, 0L, 1); /* needed in stdio */ |
745 _immediateInterrupt = 1; |
933 } |
746 |
934 first = getc(f); |
747 if (_buffered) { |
935 if (first != EOF) { |
748 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
936 second = getc(f); |
749 _INST(didWrite) = false; |
937 _immediateInterrupt = 0; |
750 fseek(f, 0L, 1); /* needed in stdio */ |
938 if (second != EOF) { |
751 } |
939 if (_INST(position) != nil) { |
752 } |
940 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 2); |
753 |
941 } |
754 do { |
942 if (msbFlag == true) { |
755 if (! _buffered) { |
943 value = ((first & 0xFF) << 8) | (second & 0xFF); |
756 cnt = read(fileno(f), &hi, 1); |
944 } else { |
757 } else { |
945 value = ((second & 0xFF) << 8) | (first & 0xFF); |
758 cnt = fread(&hi, 1, 1, f); |
946 } |
759 } |
947 RETURN (_MKSMALLINT(value)); |
760 } while ((cnt < 0) && (errno == EINTR)); |
948 } |
761 |
949 } |
762 if (cnt <= 0) { |
950 _immediateInterrupt = 0; |
763 _INST(hitEOF) = true; |
951 |
764 if (cnt < 0) |
952 if (ferror(f)) { |
765 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
953 _INST(position) = nil; |
766 _immediateInterrupt = 0; |
954 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
767 RETURN ( nil ); |
955 } else { |
768 } |
956 _INST(hitEOF) = true; |
769 |
957 RETURN (nil); |
770 do { |
958 } |
771 if (! _buffered) { |
959 } |
772 cnt = read(fileno(f), &low, 1); |
960 %}. |
773 } else { |
|
774 cnt = fread(&low, 1, 1, f); |
|
775 } |
|
776 } while ((cnt < 0) && (errno == EINTR)); |
|
777 |
|
778 _immediateInterrupt = 0; |
|
779 |
|
780 pos = _INST(position); |
|
781 if (cnt <= 0) { |
|
782 if (pos != nil) { |
|
783 _INST(position) = _MKSMALLINT(_intVal(pos) + 1); |
|
784 } |
|
785 _INST(hitEOF) = true; |
|
786 if (cnt < 0) |
|
787 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
|
788 RETURN ( _MKSMALLINT(hi & 0xFF) ); |
|
789 } |
|
790 if (pos != nil) { |
|
791 _INST(position) = _MKSMALLINT(_intVal(pos) + 2); |
|
792 } |
|
793 RETURN ( _MKSMALLINT(((hi & 0xFF)<<8) | (low & 0xFF)) ); |
|
794 } |
|
795 } |
|
796 %} |
|
797 . |
|
798 %{ /* STACK: 2000 */ |
|
799 FILE *f; |
|
800 int len; |
|
801 char buffer[1024]; |
|
802 int ch; |
|
803 int cnt = 0; |
|
804 extern int _immediateInterrupt; |
|
805 |
|
806 /* |
|
807 * text mode |
|
808 */ |
|
809 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
|
810 f = MKFD(_INST(filePointer)); |
|
811 |
|
812 _immediateInterrupt = 1; |
|
813 |
|
814 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
|
815 _INST(didWrite) = false; |
|
816 fseek(f, 0L, 1); /* needed in stdio */ |
|
817 } |
|
818 |
|
819 for (;;) { |
|
820 ch = getc(f); |
|
821 cnt++; |
|
822 |
|
823 if (ch >= ' ') break; |
|
824 if ((ch != ' ') && (ch != '\t') && (ch != '\r') |
|
825 && (ch != '\n') && (ch != 0x0b)) break; |
|
826 } |
|
827 ungetc(ch, f); |
|
828 cnt--; |
|
829 |
|
830 len = 0; |
|
831 for (;;) { |
|
832 ch = getc(f); |
|
833 if (ch == EOF) { |
|
834 _INST(hitEOF) = true; |
|
835 break; |
|
836 } |
|
837 |
|
838 ch &= 0xFF; |
|
839 if (! (((ch >= 'a') && (ch <= 'z')) || |
|
840 ((ch >= 'A') && (ch <= 'Z')) || |
|
841 ((ch >= '0') && (ch <= '9')))) { |
|
842 ungetc(ch, f); |
|
843 break; |
|
844 } |
|
845 cnt++; |
|
846 buffer[len++] = ch; |
|
847 if (len >= sizeof(buffer)-1) { |
|
848 /* emergency */ |
|
849 break; |
|
850 } |
|
851 } |
|
852 _immediateInterrupt = 0; |
|
853 |
|
854 if (_INST(position) != nil) { |
|
855 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + cnt); |
|
856 } |
|
857 buffer[len] = '\0'; |
|
858 if (len != 0) { |
|
859 RETURN ( _MKSTRING(buffer COMMA_CON) ); |
|
860 } |
|
861 RETURN ( nil ); |
|
862 } |
|
863 %} |
|
864 . |
|
865 filePointer isNil ifTrue:[^ self errorNotOpen]. |
|
866 self errorWriteOnly |
|
867 ! |
|
868 |
|
869 nextShortMSB:msbFlag |
|
870 "Read two bytes and return the value as a 16-bit signed Integer. |
|
871 If msbFlag is true, value is read with most-significant byte first, otherwise |
|
872 least-significant byte comes first. |
|
873 A nil is also returned, if endOfFile occurs after the first byte. |
|
874 Works in both binary and text modes." |
|
875 |
|
876 %{ /* NOCONTEXT */ |
|
877 extern int _immediateInterrupt; |
|
878 |
|
879 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
|
880 FILE *f; |
|
881 int first, second; |
|
882 short value; |
|
883 |
|
884 f = MKFD(_INST(filePointer)); |
|
885 |
|
886 _immediateInterrupt = 1; |
|
887 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
|
888 _INST(didWrite) = false; |
|
889 fseek(f, 0L, 1); /* needed in stdio */ |
|
890 } |
|
891 first = getc(f); |
|
892 if (first == EOF) { |
|
893 _immediateInterrupt = 0; |
|
894 _INST(hitEOF) = true; |
|
895 RETURN ( nil ); |
|
896 } |
|
897 second = getc(f); |
|
898 _immediateInterrupt = 0; |
|
899 |
|
900 if (second == EOF) { |
|
901 _INST(hitEOF) = true; |
|
902 RETURN ( nil ); |
|
903 } |
|
904 if (_INST(position) != nil) { |
|
905 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 2); |
|
906 } |
|
907 if (msbFlag == true) { |
|
908 RETURN ( _MKSMALLINT(((first & 0xFF)<<8) | (second & 0xFF)) ); |
|
909 } |
|
910 RETURN ( _MKSMALLINT(((second & 0xFF)<<8) | (first & 0xFF)) ); |
|
911 } |
|
912 %} |
|
913 . |
|
914 filePointer isNil ifTrue:[^ self errorNotOpen]. |
961 filePointer isNil ifTrue:[^ self errorNotOpen]. |
915 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
962 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
916 self primitiveFailed |
963 ^ self readError. |
917 ! |
964 ! |
918 |
965 |
919 nextUnsignedShortMSB:msbFlag |
966 nextUnsignedShortMSB:msbFlag |
920 "Read two bytes and return the value as a 16-bit unsigned Integer. |
967 "Read two bytes and return the value as a 16-bit unsigned Integer. |
921 If msbFlag is true, value is read with most-significant byte first, otherwise |
968 If msbFlag is true, value is read with most-significant byte first, otherwise |
922 least-significant byte comes first. |
969 least-significant byte comes first. |
923 A nil is also returned, if endOfFile occurs after the first byte. |
970 A nil is returned if EOF is reached (also when EOF is hit after the first byte). |
924 Works in both binary and text modes." |
971 Works in both binary and text modes." |
925 |
972 |
926 %{ /* NOCONTEXT */ |
973 %{ /* NOCONTEXT */ |
927 extern int _immediateInterrupt; |
974 extern int _immediateInterrupt; |
928 |
975 |
929 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
976 _INST(lastErrorNumber) = nil; |
930 FILE *f; |
977 if ((_INST(filePointer) != nil) |
931 int first, second; |
978 && (_INST(mode) != @symbol(writeonly))) { |
932 |
979 FILE *f; |
933 _immediateInterrupt = 1; |
980 int first, second; |
934 |
981 unsigned value; |
935 f = MKFD(_INST(filePointer)); |
982 _immediateInterrupt = 1; |
936 |
983 |
937 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
984 f = MKFD(_INST(filePointer)); |
938 _INST(didWrite) = false; |
985 |
939 fseek(f, 0L, 1); /* needed in stdio */ |
986 if ((_INST(didWrite) != false) |
940 } |
987 && (_INST(mode) == @symbol(readwrite))) { |
941 |
988 _INST(didWrite) = false; |
942 first = getc(f); |
989 fseek(f, 0L, 1); /* needed in stdio */ |
943 if (first == EOF) { |
990 } |
944 _immediateInterrupt = 0; |
991 |
945 _INST(hitEOF) = true; |
992 first = getc(f); |
946 RETURN ( nil ); |
993 if (first != EOF) { |
947 } |
994 second = getc(f); |
948 second = getc(f); |
995 _immediateInterrupt = 0; |
949 _immediateInterrupt = 0; |
996 if (second != EOF) { |
950 |
997 if (_INST(position) != nil) { |
951 if (second == EOF) { |
998 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 2); |
952 _INST(hitEOF) = true; |
999 } |
953 RETURN ( nil ); |
1000 if (msbFlag == true) { |
954 } |
1001 value = ((first & 0xFF) << 8) | (second & 0xFF); |
955 if (_INST(position) != nil) { |
1002 } else { |
956 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 2); |
1003 value = ((second & 0xFF) << 8) | (first & 0xFF); |
957 } |
1004 } |
958 if (msbFlag == true) { |
1005 RETURN (_MKSMALLINT(value)); |
959 RETURN ( _MKSMALLINT(((first & 0xFF)<<8) | (second & 0xFF)) ); |
1006 } |
960 } |
1007 } |
961 RETURN ( _MKSMALLINT(((second & 0xFF)<<8) | (first & 0xFF)) ); |
1008 _immediateInterrupt = 0; |
962 } |
1009 |
963 %} |
1010 if (ferror(f)) { |
964 . |
1011 _INST(position) = nil; |
|
1012 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
1013 } else { |
|
1014 _INST(hitEOF) = true; |
|
1015 RETURN (nil); |
|
1016 } |
|
1017 } |
|
1018 %}. |
965 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1019 filePointer isNil ifTrue:[^ self errorNotOpen]. |
966 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
1020 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
967 self primitiveFailed |
1021 ^ self readError. |
968 ! |
1022 ! |
969 |
1023 |
970 nextLongMSB:msbFlag |
1024 nextLongMSB:msbFlag |
971 "Read four bytes and return the value as a 32-bit signed Integer, which may be |
1025 "Read four bytes and return the value as a 32-bit signed Integer, |
972 a LargeInteger. |
1026 which may be a LargeInteger. |
973 If msbFlag is true, value is read with most-significant byte first, otherwise |
1027 If msbFlag is true, value is read with most-significant byte first, |
974 least-significant byte comes first. |
1028 otherwise least-significant byte comes first. |
975 A nil is returned, if endOfFile occurs before all 4 bytes have been read. |
1029 A nil is returned, if EOF is hit before all 4 bytes have been read. |
976 Works in both binary and text modes." |
1030 Works in both binary and text modes." |
977 |
1031 |
978 %{ /* NOCONTEXT */ |
1032 %{ /* NOCONTEXT */ |
979 extern int _immediateInterrupt; |
1033 extern int _immediateInterrupt; |
980 |
1034 |
981 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
1035 _INST(lastErrorNumber) = nil; |
982 FILE *f; |
1036 if ((_INST(filePointer) != nil) |
983 int first, second, third, fourth; |
1037 && (_INST(mode) != @symbol(writeonly))) { |
984 int value; |
1038 FILE *f; |
985 |
1039 int first, second, third, fourth; |
986 _immediateInterrupt = 1; |
1040 int value; |
987 f = MKFD(_INST(filePointer)); |
1041 |
988 |
1042 _immediateInterrupt = 1; |
989 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
1043 f = MKFD(_INST(filePointer)); |
990 _INST(didWrite) = false; |
1044 |
991 fseek(f, 0L, 1); /* needed in stdio */ |
1045 if ((_INST(didWrite) != false) |
992 } |
1046 && (_INST(mode) == @symbol(readwrite))) { |
993 |
1047 _INST(didWrite) = false; |
994 first = getc(f); |
1048 fseek(f, 0L, 1); /* needed in stdio */ |
995 if (first == EOF) { |
1049 } |
996 _INST(hitEOF) = true; |
1050 |
997 _immediateInterrupt = 0; |
1051 first = getc(f); |
998 RETURN ( nil ); |
1052 if (first != EOF) { |
999 } |
1053 second = getc(f); |
1000 second = getc(f); |
1054 if (second != EOF) { |
1001 if (second == EOF) { |
1055 third = getc(f); |
1002 _INST(hitEOF) = true; |
1056 if (third != EOF) { |
1003 _immediateInterrupt = 0; |
1057 fourth = getc(f); |
1004 RETURN ( nil ); |
1058 if (fourth != EOF) { |
1005 } |
1059 _immediateInterrupt = 0; |
1006 third = getc(f); |
1060 if (msbFlag == true) { |
1007 if (third == EOF) { |
1061 value = (first & 0xFF); |
1008 _INST(hitEOF) = true; |
1062 value = (value<<8) | (second & 0xFF); |
1009 _immediateInterrupt = 0; |
1063 value = (value<<8) | (third & 0xFF); |
1010 RETURN ( nil ); |
1064 value = (value<<8) | (fourth & 0xFF); |
1011 } |
1065 } else { |
1012 fourth = getc(f); |
1066 value = (fourth & 0xFF); |
1013 _immediateInterrupt = 0; |
1067 value = (value<<8) | (third & 0xFF); |
1014 |
1068 value = (value<<8) | (second & 0xFF); |
1015 if (fourth == EOF) { |
1069 value = (value<<8) | (first & 0xFF); |
1016 _INST(hitEOF) = true; |
1070 } |
1017 RETURN ( nil ); |
1071 if (_INST(position) != nil) { |
1018 } |
1072 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 4); |
1019 if (_INST(position) != nil) { |
1073 } |
1020 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 4); |
1074 if ((value >= _MIN_INT) && (value <= _MAX_INT)) { |
1021 } |
1075 RETURN ( _MKSMALLINT(value)); |
1022 if (msbFlag == true) { |
1076 } |
1023 value = ((first & 0xFF) << 24) |
1077 RETURN ( _makeLarge(value) ); |
1024 | ((second & 0xFF) << 16) |
1078 } |
1025 | ((third & 0xFF) << 8) |
1079 } |
1026 | (fourth & 0xFF); |
1080 } |
1027 } else { |
1081 } |
1028 value = ((fourth & 0xFF) << 24) |
1082 if (ferror(f)) { |
1029 | ((third & 0xFF) << 16) |
1083 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1030 | ((second & 0xFF) << 8) |
1084 _INST(position) = nil; |
1031 | (first & 0xFF); |
1085 } else { |
1032 } |
1086 _INST(hitEOF) = true; |
1033 if ((value >= _MIN_INT) && (value <= _MAX_INT)) { |
1087 RETURN (nil); |
1034 RETURN ( _MKSMALLINT(value)); |
1088 } |
1035 } |
1089 } |
1036 RETURN ( _makeLarge(value) ); |
1090 %}. |
1037 } |
|
1038 %} |
|
1039 . |
|
1040 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1091 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1041 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
1092 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
1042 self primitiveFailed |
1093 ^ self readError. |
1043 ! |
1094 ! |
1044 |
1095 |
1045 nextUnsignedLongMSB:msbFlag |
1096 nextUnsignedLongMSB:msbFlag |
1046 "Read four bytes and return the value as a 32-bit unsigned Integer, which may be |
1097 "Read four bytes and return the value as a 32-bit unsigned Integer, which may be |
1047 a LargeInteger. |
1098 a LargeInteger. |
1052 |
1103 |
1053 %{ /* NOCONTEXT */ |
1104 %{ /* NOCONTEXT */ |
1054 extern int _immediateInterrupt; |
1105 extern int _immediateInterrupt; |
1055 extern OBJ _makeULarge(); |
1106 extern OBJ _makeULarge(); |
1056 |
1107 |
1057 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
1108 _INST(lastErrorNumber) = nil; |
1058 FILE *f; |
1109 if ((_INST(filePointer) != nil) |
1059 int first, second, third, fourth; |
1110 && (_INST(mode) != @symbol(writeonly))) { |
1060 unsigned int value; |
1111 FILE *f; |
1061 |
1112 int first, second, third, fourth; |
1062 _immediateInterrupt = 1; |
1113 unsigned int value; |
1063 f = MKFD(_INST(filePointer)); |
1114 |
1064 |
1115 _immediateInterrupt = 1; |
1065 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
1116 f = MKFD(_INST(filePointer)); |
1066 _INST(didWrite) = false; |
1117 |
1067 fseek(f, 0L, 1); /* needed in stdio */ |
1118 if ((_INST(didWrite) != false) |
1068 } |
1119 && (_INST(mode) == @symbol(readwrite))) { |
1069 |
1120 _INST(didWrite) = false; |
1070 first = getc(f); |
1121 fseek(f, 0L, 1); /* needed in stdio */ |
1071 if (first == EOF) { |
1122 } |
1072 _INST(hitEOF) = true; |
1123 |
1073 _immediateInterrupt = 0; |
1124 first = getc(f); |
1074 RETURN ( nil ); |
1125 if (first != EOF) { |
1075 } |
1126 second = getc(f); |
1076 second = getc(f); |
1127 if (second != EOF) { |
1077 if (second == EOF) { |
1128 third = getc(f); |
1078 _INST(hitEOF) = true; |
1129 if (third != EOF) { |
1079 _immediateInterrupt = 0; |
1130 fourth = getc(f); |
1080 RETURN ( nil ); |
1131 if (fourth != EOF) { |
1081 } |
1132 _immediateInterrupt = 0; |
1082 third = getc(f); |
1133 if (msbFlag == true) { |
1083 if (third == EOF) { |
1134 value = (first & 0xFF); |
1084 _INST(hitEOF) = true; |
1135 value = (value<<8) | (second & 0xFF); |
1085 _immediateInterrupt = 0; |
1136 value = (value<<8) | (third & 0xFF); |
1086 RETURN ( nil ); |
1137 value = (value<<8) | (fourth & 0xFF); |
1087 } |
1138 } else { |
1088 fourth = getc(f); |
1139 value = (fourth & 0xFF); |
1089 _immediateInterrupt = 0; |
1140 value = (value<<8) | (third & 0xFF); |
1090 if (fourth == EOF) { |
1141 value = (value<<8) | (second & 0xFF); |
1091 _INST(hitEOF) = true; |
1142 value = (value<<8) | (first & 0xFF); |
1092 RETURN ( nil ); |
1143 } |
1093 } |
1144 if (_INST(position) != nil) { |
1094 if (_INST(position) != nil) { |
1145 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 4); |
1095 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 4); |
1146 } |
1096 } |
1147 if (value <= _MAX_INT) { |
1097 if (msbFlag == true) { |
1148 RETURN ( _MKSMALLINT(value)); |
1098 value = ((first & 0xFF) << 24) |
1149 } |
1099 | ((second & 0xFF) << 16) |
1150 RETURN ( _makeULarge(value) ); |
1100 | ((third & 0xFF) << 8) |
1151 } |
1101 | (fourth & 0xFF); |
1152 } |
1102 } else { |
1153 } |
1103 value = ((fourth & 0xFF) << 24) |
1154 } |
1104 | ((third & 0xFF) << 16) |
1155 if (ferror(f)) { |
1105 | ((second & 0xFF) << 8) |
1156 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1106 | (first & 0xFF); |
1157 _INST(position) = nil; |
1107 } |
1158 } else { |
1108 if (value <= _MAX_INT) { |
1159 _INST(hitEOF) = true; |
1109 RETURN ( _MKSMALLINT(value)); |
1160 RETURN (nil); |
1110 } |
1161 } |
1111 RETURN ( _makeULarge(value) ); |
1162 } |
1112 } |
1163 %}. |
1113 %} |
|
1114 . |
|
1115 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1164 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1116 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
1165 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
1117 self primitiveFailed |
1166 ^ self readError. |
|
1167 ! |
|
1168 |
|
1169 nextWord |
|
1170 "in text-mode: |
|
1171 read the alphaNumeric next word (i.e. up to non letter-or-digit). |
|
1172 return a string containing those characters. |
|
1173 in binary-mode: |
|
1174 read two bytes (msb-first) and return the value as a 16-bit unsigned Integer |
|
1175 (for compatibility with other smalltalks)" |
|
1176 |
|
1177 binary ifTrue:[ |
|
1178 ^ self nextShortMSB:true |
|
1179 ]. |
|
1180 ^ self nextAlphaNumericWord |
1118 ! |
1181 ! |
1119 |
1182 |
1120 nextLong |
1183 nextLong |
1121 "Read four bytes (msb-first) and return the value as a 32-bit signed Integer. |
1184 "Read four bytes (msb-first) and return the value as a 32-bit signed Integer. |
1122 The returned value may be a LargeInteger. |
1185 The returned value may be a LargeInteger. |
1217 extern errno; |
1283 extern errno; |
1218 OBJ oClass; |
1284 OBJ oClass; |
1219 OBJ pos; |
1285 OBJ pos; |
1220 extern int _immediateInterrupt; |
1286 extern int _immediateInterrupt; |
1221 |
1287 |
1222 if ((_INST(filePointer) != nil) && (_INST(mode) != _readonly)) { |
1288 _INST(lastErrorNumber) = nil; |
1223 if (_isSmallInteger(count) && _isSmallInteger(start)) { |
1289 if ((_INST(filePointer) != nil) |
1224 oClass = _Class(anObject); |
1290 && (_INST(mode) != @symbol(readonly))) { |
1225 switch (_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
1291 if (_isSmallInteger(count) && _isSmallInteger(start)) { |
1226 case BYTEARRAY: |
1292 oClass = _Class(anObject); |
1227 case WORDARRAY: |
1293 switch (_intVal(_ClassInstPtr(oClass)->c_flags) & ARRAYMASK) { |
1228 case LONGARRAY: |
1294 case BYTEARRAY: |
1229 case FLOATARRAY: |
1295 case WORDARRAY: |
1230 case DOUBLEARRAY: |
1296 case LONGARRAY: |
1231 break; |
1297 case FLOATARRAY: |
1232 default: |
1298 case DOUBLEARRAY: |
1233 goto bad; |
1299 break; |
1234 } |
1300 default: |
1235 cnt = _intVal(count); |
1301 goto bad; |
1236 offs = _intVal(start) - 1; |
1302 } |
1237 f = MKFD(_INST(filePointer)); |
1303 cnt = _intVal(count); |
1238 |
1304 offs = _intVal(start) - 1; |
1239 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
1305 f = MKFD(_INST(filePointer)); |
1240 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
1306 |
1241 objSize = _Size(anObject) - nInstBytes; |
1307 nInstVars = _intVal(_ClassInstPtr(oClass)->c_ninstvars); |
1242 if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) { |
1308 nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars); |
1243 cp = (char *)_InstPtr(anObject) + nInstBytes + offs; |
1309 objSize = _Size(anObject) - nInstBytes; |
1244 _immediateInterrupt = 1; |
1310 if ( (offs >= 0) && (cnt >= 0) && (objSize >= (cnt + offs)) ) { |
|
1311 cp = (char *)_InstPtr(anObject) + nInstBytes + offs; |
|
1312 _immediateInterrupt = 1; |
1245 #ifdef OLD |
1313 #ifdef OLD |
1246 if (_INST(buffered) == false) { |
1314 if (_INST(buffered) == false) { |
1247 cnt = write(fileno(f), cp, cnt); |
1315 cnt = write(fileno(f), cp, cnt); |
1248 } else |
1316 } else |
1249 #endif |
1317 #endif |
1250 { |
1318 { |
1251 if ((_INST(didWrite) != true) && (_INST(mode) == _readwrite)) { |
1319 if ((_INST(didWrite) != true) |
1252 _INST(didWrite) = true; |
1320 && (_INST(mode) == @symbol(readwrite))) { |
1253 fseek(f, 0L, 1); /* needed in stdio */ |
1321 _INST(didWrite) = true; |
1254 } |
1322 fseek(f, 0L, 1); /* needed in stdio */ |
1255 cnt = fwrite(cp, 1, cnt, f); |
1323 } |
1256 } |
1324 cnt = fwrite(cp, 1, cnt, f); |
|
1325 } |
1257 #ifndef OLD |
1326 #ifndef OLD |
1258 if (_INST(buffered) == false) { |
1327 if (_INST(buffered) == false) { |
1259 fflush(f); |
1328 fflush(f); |
1260 } |
1329 } |
1261 #endif |
1330 #endif |
1262 _immediateInterrupt = 0; |
1331 _immediateInterrupt = 0; |
1263 if (cnt >= 0) { |
1332 if (cnt >= 0) { |
1264 pos = _INST(position); |
1333 pos = _INST(position); |
1265 if (pos != nil) |
1334 if (pos != nil) |
1266 _INST(position) = _MKSMALLINT(_intVal(pos) + cnt); |
1335 _INST(position) = _MKSMALLINT(_intVal(pos) + cnt); |
1267 RETURN ( _MKSMALLINT(cnt) ); |
1336 RETURN ( _MKSMALLINT(cnt) ); |
1268 } |
1337 } |
1269 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
1338 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1270 RETURN ( nil ); |
1339 } |
1271 } |
1340 } |
1272 } |
|
1273 } |
1341 } |
1274 bad: ; |
1342 bad: ; |
1275 %} |
1343 %}. |
1276 . |
1344 lastErrorNumber notNil ifTrue:[^ self writeError]. |
1277 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1345 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1278 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
1346 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
1279 self primitiveFailed |
1347 ^ self primitiveFailed |
1280 ! |
1348 ! |
1281 |
1349 |
1282 nextPutShort:aNumber MSB:msbFlag |
1350 nextPutShort:aNumber MSB:msbFlag |
1283 "Write the argument, aNumber as a short (two bytes). If msbFlag is |
1351 "Write the argument, aNumber as a short (two bytes). If msbFlag is |
1284 true, data is written most-significant byte first; otherwise least |
1352 true, data is written most-significant byte first; otherwise least |
1285 first. Returns the receiver on ok, nil on error. |
1353 first. |
1286 Works in both binary and text modes." |
1354 Works in both binary and text modes." |
1287 |
1355 |
1288 %{ /* NOCONTEXT */ |
1356 %{ /* NOCONTEXT */ |
1289 |
1357 |
1290 int num; |
1358 int num; |
1292 FILE *f; |
1360 FILE *f; |
1293 extern errno; |
1361 extern errno; |
1294 extern int _immediateInterrupt; |
1362 extern int _immediateInterrupt; |
1295 int cnt; |
1363 int cnt; |
1296 |
1364 |
1297 if ((_INST(filePointer) != nil) && (_INST(mode) != _readonly)) { |
1365 _INST(lastErrorNumber) = nil; |
1298 if (_isSmallInteger(aNumber)) { |
1366 if ((_INST(filePointer) != nil) |
1299 num = _intVal(aNumber); |
1367 && (_INST(mode) != @symbol(readonly)) |
1300 if (msbFlag == true) { |
1368 && _isSmallInteger(aNumber)) { |
1301 bytes[0] = (num >> 8) & 0xFF; |
1369 num = _intVal(aNumber); |
1302 bytes[1] = num & 0xFF; |
1370 if (msbFlag == true) { |
1303 } else { |
1371 bytes[0] = (num >> 8) & 0xFF; |
1304 bytes[1] = (num >> 8) & 0xFF; |
1372 bytes[1] = num & 0xFF; |
1305 bytes[0] = num & 0xFF; |
1373 } else { |
1306 } |
1374 bytes[1] = (num >> 8) & 0xFF; |
1307 |
1375 bytes[0] = num & 0xFF; |
1308 f = MKFD(_INST(filePointer)); |
1376 } |
1309 _immediateInterrupt = 1; |
1377 |
|
1378 f = MKFD(_INST(filePointer)); |
|
1379 _immediateInterrupt = 1; |
1310 #ifdef OLD |
1380 #ifdef OLD |
1311 if (_INST(buffered) == false) { |
1381 if (_INST(buffered) == false) { |
1312 cnt = write(fileno(f), bytes, 2); |
1382 cnt = write(fileno(f), bytes, 2); |
1313 } else |
1383 } else |
1314 #endif |
1384 #endif |
1315 { |
1385 { |
1316 if ((_INST(didWrite) != true) && (_INST(mode) == _readwrite)) { |
1386 if ((_INST(didWrite) != true) |
1317 _INST(didWrite) = true; |
1387 && (_INST(mode) == @symbol(readwrite))) { |
1318 fseek(f, 0L, 1); /* needed in stdio */ |
1388 _INST(didWrite) = true; |
1319 } |
1389 fseek(f, 0L, 1); /* needed in stdio */ |
1320 cnt = fwrite(bytes, 1, 2, f); |
1390 } |
1321 } |
1391 cnt = fwrite(bytes, 1, 2, f); |
|
1392 } |
1322 #ifndef OLD |
1393 #ifndef OLD |
1323 if (_INST(buffered) == false) { |
1394 if (_INST(buffered) == false) { |
1324 fflush(f); |
1395 fflush(f); |
1325 } |
1396 } |
1326 #endif |
1397 #endif |
1327 _immediateInterrupt = 0; |
1398 _immediateInterrupt = 0; |
1328 if (cnt == 2) { |
1399 if (cnt == 2) { |
1329 if (_INST(position) != nil) { |
1400 if (_INST(position) != nil) { |
1330 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 2); |
1401 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 2); |
1331 } |
1402 } |
1332 RETURN ( self ); |
1403 RETURN ( self ); |
1333 } |
1404 } |
1334 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
1405 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1335 return ( nil ); |
1406 } |
1336 } |
1407 %}. |
1337 } |
1408 lastErrorNumber notNil ifTrue:[^ self writeError]. |
1338 %} |
|
1339 . |
|
1340 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1409 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1341 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
1410 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
1342 self argumentMustBeInteger |
1411 self argumentMustBeInteger |
1343 ! |
1412 ! |
1344 |
1413 |
1345 nextPutLong:aNumber MSB:msbFlag |
1414 nextPutLong:aNumber MSB:msbFlag |
1346 "Write the argument, aNumber as a long (four bytes). If msbFlag is |
1415 "Write the argument, aNumber as a long (four bytes). If msbFlag is |
1347 true, data is written most-significant byte first; otherwise least |
1416 true, data is written most-significant byte first; otherwise least |
1348 first. Returns the receiver on ok, nil on error. |
1417 first. |
1349 Works in both binary and text modes." |
1418 Works in both binary and text modes." |
1350 |
1419 |
1351 %{ /* NOCONTEXT */ |
1420 %{ /* NOCONTEXT */ |
1352 |
1421 |
1353 int num; |
1422 int num; |
1355 FILE *f; |
1424 FILE *f; |
1356 extern errno; |
1425 extern errno; |
1357 int cnt; |
1426 int cnt; |
1358 extern int _immediateInterrupt; |
1427 extern int _immediateInterrupt; |
1359 |
1428 |
1360 if ((_INST(filePointer) != nil) && (_INST(mode) != _readonly)) { |
1429 _INST(lastErrorNumber) = nil; |
1361 if (_isSmallInteger(aNumber)) { |
1430 if ((_INST(filePointer) != nil) |
1362 num = _intVal(aNumber); |
1431 && (_INST(mode) != @symbol(readonly)) |
1363 if (msbFlag == true) { |
1432 && _isSmallInteger(aNumber)) { |
1364 bytes[0] = (num >> 24) & 0xFF; |
1433 num = _intVal(aNumber); |
1365 bytes[1] = (num >> 16) & 0xFF; |
1434 if (msbFlag == true) { |
1366 bytes[2] = (num >> 8) & 0xFF; |
1435 bytes[0] = (num >> 24) & 0xFF; |
1367 bytes[3] = num & 0xFF; |
1436 bytes[1] = (num >> 16) & 0xFF; |
1368 } else { |
1437 bytes[2] = (num >> 8) & 0xFF; |
1369 bytes[3] = (num >> 24) & 0xFF; |
1438 bytes[3] = num & 0xFF; |
1370 bytes[2] = (num >> 16) & 0xFF; |
1439 } else { |
1371 bytes[1] = (num >> 8) & 0xFF; |
1440 bytes[3] = (num >> 24) & 0xFF; |
1372 bytes[0] = num & 0xFF; |
1441 bytes[2] = (num >> 16) & 0xFF; |
1373 } |
1442 bytes[1] = (num >> 8) & 0xFF; |
1374 |
1443 bytes[0] = num & 0xFF; |
1375 f = MKFD(_INST(filePointer)); |
1444 } |
1376 _immediateInterrupt = 1; |
1445 |
|
1446 f = MKFD(_INST(filePointer)); |
|
1447 _immediateInterrupt = 1; |
1377 #ifdef OLD |
1448 #ifdef OLD |
1378 if (_INST(buffered) == false) { |
1449 if (_INST(buffered) == false) { |
1379 cnt = write(fileno(f), bytes, 4); |
1450 cnt = write(fileno(f), bytes, 4); |
1380 } else |
1451 } else |
1381 #endif |
1452 #endif |
1382 { |
1453 { |
1383 cnt = fwrite(bytes, 1, 4, f); |
1454 if ((_INST(didWrite) != true) |
1384 } |
1455 && (_INST(mode) == @symbol(readwrite))) { |
|
1456 _INST(didWrite) = true; |
|
1457 fseek(f, 0L, 1); /* needed in stdio */ |
|
1458 } |
|
1459 cnt = fwrite(bytes, 1, 4, f); |
|
1460 } |
1385 #ifndef OLD |
1461 #ifndef OLD |
1386 if (_INST(buffered) == false) { |
1462 if (_INST(buffered) == false) { |
1387 fflush(f); |
1463 fflush(f); |
1388 } |
1464 } |
1389 #endif |
1465 #endif |
1390 _immediateInterrupt = 0; |
1466 _immediateInterrupt = 0; |
1391 if (cnt == 4) { |
1467 if (cnt == 4) { |
1392 if (_INST(position) != nil) { |
1468 if (_INST(position) != nil) { |
1393 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 4); |
1469 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + 4); |
1394 } |
1470 } |
1395 RETURN ( self ); |
1471 RETURN ( self ); |
1396 } |
1472 } |
1397 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
1473 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1398 return ( nil ); |
1474 } |
1399 } |
1475 %}. |
1400 } |
|
1401 %} |
|
1402 . |
|
1403 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1476 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1404 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
1477 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
|
1478 lastErrorNumber notNil ifTrue:[^ self writeError]. |
1405 |
1479 |
1406 aNumber isInteger ifTrue:[ |
1480 aNumber isInteger ifTrue:[ |
1407 msbFlag ifTrue:[ |
1481 msbFlag ifTrue:[ |
1408 "high word first" |
1482 "high word first" |
1409 (self nextShortPut:(aNumber // 16r10000) MSB:true) isNil ifTrue:[^ nil]. |
1483 (self nextShortPut:(aNumber // 16r10000) MSB:true) isNil ifTrue:[^ nil]. |
1410 ^ self nextShortPut:(aNumber \\ 16r10000) MSB:true |
1484 ^ self nextShortPut:(aNumber \\ 16r10000) MSB:true |
1411 ]. |
1485 ]. |
1412 "low word first" |
1486 "low word first" |
1413 (self nextShortPut:(aNumber \\ 16r10000) MSB:false) isNil ifTrue:[^ nil]. |
1487 (self nextShortPut:(aNumber \\ 16r10000) MSB:false) isNil ifTrue:[^ nil]. |
1414 ^ self nextShortPut:(aNumber // 16r10000) MSB:false. |
1488 ^ self nextShortPut:(aNumber // 16r10000) MSB:false. |
1415 ]. |
1489 ]. |
1416 self argumentMustBeInteger |
1490 self argumentMustBeInteger |
1417 ! ! |
1491 ! ! |
1418 |
1492 |
1419 !ExternalStream methodsFor:'reading'! |
1493 !ExternalStream methodsFor:'reading'! |
1637 int len, cnt; |
1720 int len, cnt; |
1638 extern errno; |
1721 extern errno; |
1639 OBJ pos; |
1722 OBJ pos; |
1640 extern int _immediateInterrupt; |
1723 extern int _immediateInterrupt; |
1641 |
1724 |
1642 if ((_INST(filePointer) != nil) && (_INST(mode) != _readonly)) { |
1725 _INST(lastErrorNumber) = nil; |
1643 cp = NULL; |
1726 if ((_INST(filePointer) != nil) |
1644 if (__isString(aCollection) || __isSymbol(aCollection)) { |
1727 && (_INST(mode) != @symbol(readonly))) { |
1645 cp = _stringVal(aCollection); |
1728 cp = NULL; |
1646 len = _stringSize(aCollection); |
1729 if (__isString(aCollection) || __isSymbol(aCollection)) { |
1647 } else { |
1730 cp = _stringVal(aCollection); |
1648 if (_INST(binary) == true) { |
1731 len = _stringSize(aCollection); |
1649 if (__isByteArray(aCollection)) { |
1732 } else { |
1650 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1733 if (_INST(binary) == true) { |
1651 len = _byteArraySize(aCollection); |
1734 if (__isByteArray(aCollection)) { |
1652 } else { |
1735 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1653 if (__isBytes(aCollection)) { |
1736 len = _byteArraySize(aCollection); |
1654 int nInst; |
1737 } else { |
1655 |
1738 if (__isBytes(aCollection)) { |
1656 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1739 int nInst; |
1657 len = _byteArraySize(aCollection); |
1740 |
1658 nInst = _intVal(_ClassInstPtr(_qClass(aCollection))->c_ninstvars); |
1741 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1659 cp += __OBJS2BYTES__(nInst); |
1742 len = _byteArraySize(aCollection); |
1660 len -= __OBJS2BYTES__(nInst); |
1743 nInst = _intVal(_ClassInstPtr(_qClass(aCollection))->c_ninstvars); |
1661 } |
1744 cp += __OBJS2BYTES__(nInst); |
1662 } |
1745 len -= __OBJS2BYTES__(nInst); |
1663 } |
1746 } |
1664 } |
1747 } |
1665 if (cp != NULL) { |
1748 } |
1666 f = MKFD(_INST(filePointer)); |
1749 } |
1667 |
1750 if (cp != NULL) { |
1668 _immediateInterrupt = 1; |
1751 f = MKFD(_INST(filePointer)); |
|
1752 |
|
1753 _immediateInterrupt = 1; |
1669 #ifdef OLD |
1754 #ifdef OLD |
1670 if (_INST(buffered) == false) { |
1755 if (_INST(buffered) == false) { |
1671 cnt = write(fileno(f), cp, len); |
1756 cnt = write(fileno(f), cp, len); |
1672 } else |
1757 } else |
1673 #endif |
1758 #endif |
1674 { |
1759 { |
1675 if ((_INST(didWrite) != true) && (_INST(mode) == _readwrite)) { |
1760 if ((_INST(didWrite) != true) |
1676 _INST(didWrite) = true; |
1761 && (_INST(mode) == @symbol(readwrite))) { |
1677 fseek(f, 0L, 1); /* needed in stdio */ |
1762 _INST(didWrite) = true; |
1678 } |
1763 fseek(f, 0L, 1); /* needed in stdio */ |
1679 cnt = fwrite(cp, 1, len, f); |
1764 } |
1680 } |
1765 do { |
|
1766 cnt = fwrite(cp, 1, len, f); |
|
1767 if (cnt != len) { |
|
1768 if (cnt >= 0) { |
|
1769 if (errno == EINTR) { |
|
1770 cp += cnt; |
|
1771 len -= cnt; |
|
1772 } |
|
1773 } |
|
1774 } |
|
1775 } while ((cnt != len) && (errno == EINTR)); |
|
1776 } |
1681 #ifndef OLD |
1777 #ifndef OLD |
1682 if (_INST(buffered) == false) { |
1778 if (_INST(buffered) == false) { |
1683 fflush(f); |
1779 fflush(f); |
1684 } |
1780 } |
1685 #endif |
1781 #endif |
1686 _immediateInterrupt = 0; |
1782 _immediateInterrupt = 0; |
1687 if (cnt == len) { |
1783 if (cnt == len) { |
1688 pos = _INST(position); |
1784 pos = _INST(position); |
1689 if (pos != nil) { |
1785 if (pos != nil) { |
1690 _INST(position) = _MKSMALLINT(_intVal(pos) + len); |
1786 _INST(position) = _MKSMALLINT(_intVal(pos) + len); |
1691 } |
1787 } |
1692 RETURN ( self ); |
1788 RETURN ( self ); |
1693 } |
1789 } |
1694 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
1790 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1695 RETURN ( nil ); |
1791 } |
1696 } |
1792 } |
1697 } |
1793 %}. |
1698 %} |
1794 lastErrorNumber notNil ifTrue:[^ self writeError]. |
1699 . |
|
1700 ^ super nextPutAll:aCollection |
1795 ^ super nextPutAll:aCollection |
1701 ! |
1796 ! |
1702 |
1797 |
1703 nextPutAll:aCollection startingAt:start to:stop |
1798 nextPutAll:aCollection startingAt:start to:stop |
1704 "write a range of elements of the argument, aCollection. |
1799 "write a range of elements of the argument, aCollection. |
1711 unsigned char *cp; |
1806 unsigned char *cp; |
1712 int len, cnt, index1, index2; |
1807 int len, cnt, index1, index2; |
1713 extern errno; |
1808 extern errno; |
1714 extern int _immediateInterrupt; |
1809 extern int _immediateInterrupt; |
1715 |
1810 |
1716 if ((_INST(filePointer) != nil) && (_INST(mode) != _readonly)) { |
1811 _INST(lastErrorNumber) = nil; |
1717 if (_isSmallInteger(start) && _isSmallInteger(stop)) { |
1812 if ((_INST(filePointer) != nil) |
1718 cp = NULL; |
1813 && (_INST(mode) != @symbol(readonly))) { |
1719 if (_INST(binary) != true) { |
1814 if (_isSmallInteger(start) && _isSmallInteger(stop)) { |
1720 if (__isString(aCollection) || __isSymbol(aCollection)) { |
1815 cp = NULL; |
1721 cp = _stringVal(aCollection); |
1816 if (_INST(binary) != true) { |
1722 len = _stringSize(aCollection); |
1817 if (__isString(aCollection) || __isSymbol(aCollection)) { |
1723 } |
1818 cp = _stringVal(aCollection); |
1724 } else { |
1819 len = _stringSize(aCollection); |
1725 if (__isByteArray(aCollection)) { |
1820 } |
1726 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1821 } else { |
1727 len = _byteArraySize(aCollection); |
1822 if (__isByteArray(aCollection)) { |
1728 } else { |
1823 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1729 if (__isBytes(aCollection)) { |
1824 len = _byteArraySize(aCollection); |
1730 int nInst; |
1825 } else { |
1731 |
1826 if (__isBytes(aCollection)) { |
1732 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1827 int nInst; |
1733 len = _byteArraySize(aCollection); |
1828 |
1734 nInst = _intVal(_ClassInstPtr(_qClass(aCollection))->c_ninstvars); |
1829 cp = _ByteArrayInstPtr(aCollection)->ba_element; |
1735 cp += __OBJS2BYTES__(nInst); |
1830 len = _byteArraySize(aCollection); |
1736 len -= __OBJS2BYTES__(nInst); |
1831 nInst = _intVal(_ClassInstPtr(_qClass(aCollection))->c_ninstvars); |
1737 } |
1832 cp += __OBJS2BYTES__(nInst); |
1738 } |
1833 len -= __OBJS2BYTES__(nInst); |
1739 } |
1834 } |
1740 if (cp != NULL) { |
1835 } |
1741 f = MKFD(_INST(filePointer)); |
1836 } |
1742 index1 = _intVal(start); |
1837 if (cp != NULL) { |
1743 index2 = _intVal(stop); |
1838 f = MKFD(_INST(filePointer)); |
1744 if ((index1 < 1) || (index2 > len) || (index2 < index1)) { |
1839 index1 = _intVal(start); |
1745 RETURN ( self ); |
1840 index2 = _intVal(stop); |
1746 } |
1841 if ((index1 < 1) || (index2 > len) || (index2 < index1)) { |
1747 if (index2 > len) |
1842 RETURN ( self ); |
1748 index2 = len; |
1843 } |
1749 |
1844 if (index2 > len) |
1750 _immediateInterrupt = 1; |
1845 index2 = len; |
1751 len = index2 - index1 + 1; |
1846 |
1752 #ifdef OLD |
1847 _immediateInterrupt = 1; |
1753 if (_INST(buffered) == false) { |
1848 len = index2 - index1 + 1; |
1754 cnt = write(fileno(f), cp + index1 - 1, len); |
1849 |
1755 } else |
1850 if ((_INST(didWrite) != true) |
1756 #endif |
1851 && (_INST(mode) == @symbol(readwrite))) { |
1757 { |
1852 _INST(didWrite) = true; |
1758 if ((_INST(didWrite) != true) && (_INST(mode) == _readwrite)) { |
1853 fseek(f, 0L, 1); /* needed in stdio */ |
1759 _INST(didWrite) = true; |
1854 } |
1760 fseek(f, 0L, 1); /* needed in stdio */ |
1855 |
1761 } |
1856 do { |
1762 cnt = fwrite(cp + index1 - 1, 1, len, f); |
1857 cnt = fwrite(cp + index1 - 1, 1, len, f); |
1763 } |
1858 if (cnt != len) { |
1764 #ifndef OLD |
1859 if (cnt >= 0) { |
1765 if (_INST(buffered) == false) { |
1860 if (errno == EINTR) { |
1766 fflush(f); |
1861 cp += cnt; |
1767 } |
1862 len -= cnt; |
1768 #endif |
1863 } |
1769 _immediateInterrupt = 0; |
1864 } |
1770 if (cnt == len) { |
1865 } |
1771 if (_INST(position) != nil) { |
1866 } while ((cnt != len) && (errno == EINTR)); |
1772 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + len); |
1867 |
1773 } |
1868 if (_INST(buffered) == false) { |
1774 RETURN ( self ); |
1869 fflush(f); |
1775 } |
1870 } |
1776 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
1871 |
1777 RETURN ( nil ); |
1872 _immediateInterrupt = 0; |
1778 } |
1873 if (cnt == len) { |
1779 } |
1874 if (_INST(position) != nil) { |
1780 } |
1875 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + len); |
1781 %} |
1876 } |
1782 . |
1877 RETURN ( self ); |
|
1878 } |
|
1879 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
1880 } |
|
1881 } |
|
1882 } |
|
1883 %}. |
|
1884 lastErrorNumber notNil ifTrue:[^ self writeError]. |
1783 ^ super nextPutAll:aCollection startingAt:start to:stop |
1885 ^ super nextPutAll:aCollection startingAt:start to:stop |
1784 ! |
1886 ! |
1785 |
1887 |
1786 cr |
1888 cr |
1787 "reimplemented for speed" |
1889 "reimplemented for speed" |
1851 char *rslt; |
1952 char *rslt; |
1852 extern errno; |
1953 extern errno; |
1853 int fd, ch; |
1954 int fd, ch; |
1854 int _buffered; |
1955 int _buffered; |
1855 |
1956 |
1856 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
1957 _INST(lastErrorNumber) = nil; |
1857 if (_INST(binary) != true) { |
1958 if ((_INST(filePointer) != nil) |
1858 f = MKFD(_INST(filePointer)); |
1959 && (_INST(mode) != @symbol(writeonly))) { |
1859 _immediateInterrupt = 1; |
1960 if (_INST(binary) != true) { |
1860 buffer[0] = 0; |
1961 f = MKFD(_INST(filePointer)); |
1861 |
1962 _immediateInterrupt = 1; |
1862 _buffered = (_INST(buffered) == true); |
1963 buffer[0] = 0; |
1863 |
1964 |
1864 /* |
1965 _buffered = (_INST(buffered) == true); |
1865 * mhmh - the following code looks ok to me, |
1966 |
1866 * but seems not to work for sockets |
1967 /* |
1867 */ |
1968 * mhmh - the following code looks ok to me, |
|
1969 * but seems not to work for sockets |
|
1970 */ |
1868 #ifdef DOES_NOT_WORK |
1971 #ifdef DOES_NOT_WORK |
1869 if (_INST(mode) == _readwrite) |
1972 if (_INST(mode) == _readwrite) |
1870 fseek(f, 0L, 1); /* needed in stdio */ |
1973 fseek(f, 0L, 1); /* needed in stdio */ |
1871 do { |
1974 do { |
1872 rslt = fgets(buffer, sizeof(buffer), f); |
1975 rslt = fgets(buffer, sizeof(buffer), f); |
1873 } while ((rslt == NULL) && (errno == EINTR)); |
1976 } while ((rslt == NULL) && (errno == EINTR)); |
1874 #else |
1977 #else |
1875 if (_buffered) { |
1978 if (_buffered) { |
1876 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
1979 if ((_INST(didWrite) != false) |
1877 _INST(didWrite) = false; |
1980 && (_INST(mode) == @symbol(readwrite))) { |
1878 fseek(f, 0L, 1); /* needed in stdio */ |
1981 _INST(didWrite) = false; |
1879 } |
1982 fseek(f, 0L, 1); /* needed in stdio */ |
1880 } |
1983 } |
1881 rslt = buffer; |
1984 } |
1882 fd = fileno(f); |
1985 rslt = buffer; |
1883 for (;;) { |
1986 fd = fileno(f); |
1884 if (_buffered) { |
1987 for (;;) { |
1885 ch = getc(f); |
1988 if (_buffered) { |
1886 if (ch == EOF) |
1989 ch = getc(f); |
1887 len = 0; |
1990 if (ch == EOF) { |
1888 else { |
1991 if (ferror(f)) { |
1889 len = 1; |
1992 if (errno == EINTR) { |
1890 *rslt = ch; |
1993 clearerr(f); |
1891 } |
1994 continue; |
1892 } else { |
1995 } |
1893 do { |
1996 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1894 len = read(fd, rslt, 1); |
1997 } |
1895 } while ((len < 0) && (errno == EINTR)); |
1998 len = 0; |
1896 } |
1999 } else { |
1897 if (len <= 0) { |
2000 len = 1; |
1898 if (rslt == buffer) { |
2001 *rslt = ch; |
1899 rslt = NULL; |
2002 } |
1900 } else { |
2003 } else { |
1901 *rslt = '\0'; |
2004 do { |
1902 } |
2005 len = read(fd, rslt, 1); |
1903 break; |
2006 } while ((len < 0) && (errno == EINTR)); |
1904 } |
2007 } |
1905 rslt++; |
2008 if (len <= 0) { |
1906 if (*(rslt-1) == '\n') { |
2009 if (rslt == buffer) { |
1907 *rslt = '\0'; |
2010 rslt = NULL; |
1908 break; |
2011 } else { |
1909 } |
2012 *rslt = '\0'; |
1910 if (rslt == (buffer + sizeof(buffer) - 1)) { |
2013 } |
1911 *rslt = '\0'; |
2014 break; |
1912 break; |
2015 } |
1913 } |
2016 rslt++; |
1914 } |
2017 if (*(rslt-1) == '\n') { |
|
2018 *rslt = '\0'; |
|
2019 break; |
|
2020 } |
|
2021 if (rslt == (buffer + sizeof(buffer) - 1)) { |
|
2022 *rslt = '\0'; |
|
2023 break; |
|
2024 } |
|
2025 } |
1915 #endif |
2026 #endif |
1916 _immediateInterrupt = 0; |
2027 _immediateInterrupt = 0; |
1917 if (rslt != NULL) { |
2028 if (rslt != NULL) { |
1918 len = strlen(buffer); |
2029 len = strlen(buffer); |
1919 if (_INST(position) != nil) { |
2030 if (_INST(position) != nil) { |
1920 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + len + 1); |
2031 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + len + 1); |
1921 } |
2032 } |
1922 /* remove EOL character */ |
2033 /* remove EOL character */ |
1923 if ((len != 0) && (buffer[len-1] == '\n')) { |
2034 if ((len != 0) && (buffer[len-1] == '\n')) { |
1924 buffer[--len] = '\0'; |
2035 buffer[--len] = '\0'; |
1925 } |
2036 } |
1926 if ((len != 0) && (buffer[len-1] == '\r')) { |
2037 if ((len != 0) && (buffer[len-1] == '\r')) { |
1927 buffer[--len] = '\0'; |
2038 buffer[--len] = '\0'; |
1928 } |
2039 } |
1929 RETURN ( _MKSTRING(buffer COMMA_CON) ); |
2040 RETURN ( _MKSTRING(buffer COMMA_CON) ); |
1930 } |
2041 } |
1931 _INST(hitEOF) = true; |
2042 if (ferror(f)) { |
1932 RETURN ( nil ); |
2043 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1933 } |
2044 } else { |
1934 } |
2045 _INST(hitEOF) = true; |
1935 %} |
2046 RETURN ( nil ); |
1936 . |
2047 } |
|
2048 } |
|
2049 } |
|
2050 %}. |
|
2051 lastErrorNumber notNil ifTrue:[^ self readError]. |
1937 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2052 filePointer isNil ifTrue:[^ self errorNotOpen]. |
1938 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
2053 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
1939 self errorBinary |
2054 self errorBinary |
1940 ! |
2055 ! |
1941 |
2056 |
1949 OBJ pos; |
2064 OBJ pos; |
1950 char *s; |
2065 char *s; |
1951 extern errno; |
2066 extern errno; |
1952 extern int _immediateInterrupt; |
2067 extern int _immediateInterrupt; |
1953 |
2068 |
1954 if ((_INST(filePointer) != nil) && (_INST(mode) != _readonly)) { |
2069 _INST(lastErrorNumber) = nil; |
1955 if (_INST(binary) != true) { |
2070 if ((_INST(filePointer) != nil) |
1956 if (__isString(aString)) { |
2071 && (_INST(mode) != @symbol(readonly))) { |
1957 f = MKFD(_INST(filePointer)); |
2072 if (_INST(binary) != true) { |
1958 s = (char *) _stringVal(aString); |
2073 if (__isString(aString)) { |
1959 len = _stringSize(aString); |
2074 f = MKFD(_INST(filePointer)); |
1960 |
2075 s = (char *) _stringVal(aString); |
1961 _immediateInterrupt = 1; |
2076 len = _stringSize(aString); |
|
2077 |
|
2078 _immediateInterrupt = 1; |
1962 #ifdef OLD |
2079 #ifdef OLD |
1963 if (_INST(buffered) == false) { |
2080 if (_INST(buffered) == false) { |
1964 cnt = write(fileno(f), s, len); |
2081 cnt = write(fileno(f), s, len); |
1965 } else |
2082 } else |
1966 #endif |
2083 #endif |
1967 { |
2084 { |
1968 if ((_INST(didWrite) != true) && (_INST(mode) == _readwrite)) { |
2085 if ((_INST(didWrite) != true) |
1969 _INST(didWrite) = true; |
2086 && (_INST(mode) == @symbol(readwrite))) { |
1970 fseek(f, 0L, 1); /* needed in stdio */ |
2087 _INST(didWrite) = true; |
1971 } |
2088 fseek(f, 0L, 1); /* needed in stdio */ |
1972 cnt = fwrite(s, 1, len, f); |
2089 } |
1973 } |
2090 cnt = fwrite(s, 1, len, f); |
1974 if (cnt == len) { |
2091 } |
|
2092 if (cnt == len) { |
1975 #ifdef OLD |
2093 #ifdef OLD |
1976 if (_INST(buffered) == false) { |
2094 if (_INST(buffered) == false) { |
1977 cnt = write(fileno(f), "\n", 1); |
2095 cnt = write(fileno(f), "\n", 1); |
1978 } else |
2096 } else |
1979 #endif |
2097 #endif |
1980 { |
2098 { |
1981 cnt = fwrite("\n", 1, 1, f); |
2099 cnt = fwrite("\n", 1, 1, f); |
1982 } |
2100 } |
1983 #ifndef OLD |
2101 #ifndef OLD |
1984 if (_INST(buffered) == false) { |
2102 if (_INST(buffered) == false) { |
1985 fflush(f); |
2103 fflush(f); |
1986 } |
2104 } |
1987 #endif |
2105 #endif |
1988 if (cnt == 1) { |
2106 if (cnt == 1) { |
1989 pos = _INST(position); |
2107 pos = _INST(position); |
1990 if (pos != nil) { |
2108 if (pos != nil) { |
1991 _INST(position) = _MKSMALLINT(_intVal(pos)+len+1); |
2109 _INST(position) = _MKSMALLINT(_intVal(pos)+len+1); |
1992 } |
2110 } |
1993 _immediateInterrupt = 0; |
2111 _immediateInterrupt = 0; |
1994 RETURN ( self ); |
2112 RETURN ( self ); |
1995 } |
2113 } |
1996 } |
2114 } |
1997 _immediateInterrupt = 0; |
2115 _immediateInterrupt = 0; |
1998 ExternalStream_LastErrorNumber = _MKSMALLINT(errno); |
2116 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
1999 RETURN ( nil ); |
2117 } |
2000 } |
2118 } |
2001 } |
2119 } |
2002 } |
2120 %}. |
2003 %} |
2121 lastErrorNumber notNil ifTrue:[^ self writeError]. |
2004 . |
|
2005 super nextPutAll:aString. |
2122 super nextPutAll:aString. |
2006 self cr. |
2123 self cr. |
2007 ! |
2124 ! |
2008 |
2125 |
2009 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil |
2126 nextPutLinesFrom:aStream upToLineStartingWith:aStringOrNil |
2010 "read from aStream up to and including a line starting with aStringOrNil |
2127 "read from aStream up to and including a line starting with aStringOrNil |
2011 and append it to self. |
2128 and append it to self. |
2012 can be used to copy/create large files or copy from a pipe/socket. |
2129 Can be used to copy/create large files or copy from a pipe/socket. |
2013 |
2130 |
2014 If aStringOrNil is nil or not matched, copy preceeds to the end. |
2131 If aStringOrNil is nil or not matched, copy preceeds to the end. |
2015 (this allows for example to read a Socket and transfer the data quickly |
2132 (this allows for example to read a Socket and transfer the data quickly |
2016 into a file - without creating zillions of temporary strings)" |
2133 into a file - without creating zillions of temporary strings)" |
2017 |
2134 |
2018 |srcFilePointer| |
2135 |srcFilePointer readError| |
2019 |
2136 |
2020 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
2137 (mode == #readonly) ifTrue:[^ self errorReadOnly]. |
2021 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2138 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2022 srcFilePointer := aStream filePointer. |
2139 srcFilePointer := aStream filePointer. |
2023 srcFilePointer isNil ifTrue:[^ aStream errorNotOpen]. |
2140 srcFilePointer isNil ifTrue:[^ aStream errorNotOpen]. |
2302 The other threads are not affected by the wait." |
2455 The other threads are not affected by the wait." |
2303 |
2456 |
2304 |fd outputSema canWrite wasBlocked| |
2457 |fd outputSema canWrite wasBlocked| |
2305 |
2458 |
2306 filePointer isNil ifTrue:[ |
2459 filePointer isNil ifTrue:[ |
2307 ^ self errorNotOpen |
2460 ^ self errorNotOpen |
2308 ]. |
2461 ]. |
2309 mode == #readonly ifTrue:[ |
2462 mode == #readonly ifTrue:[ |
2310 ^ self errorReadOnly |
2463 ^ self errorReadOnly |
2311 ]. |
2464 ]. |
2312 |
2465 |
2313 fd := self fileDescriptor. |
2466 fd := self fileDescriptor. |
2314 (OperatingSystem writeCheck:fd) ifTrue:[^ true]. |
2467 (OperatingSystem writeCheck:fd) ifTrue:[^ true]. |
2315 |
2468 |
2316 wasBlocked := OperatingSystem blockInterrupts. |
2469 wasBlocked := OperatingSystem blockInterrupts. |
2317 canWrite := OperatingSystem writeCheck:fd. |
2470 canWrite := OperatingSystem writeCheck:fd. |
2318 canWrite ifFalse:[ |
2471 canWrite ifFalse:[ |
2319 outputSema := Semaphore new. |
2472 outputSema := Semaphore new. |
2320 timeout notNil ifTrue:[ |
2473 timeout notNil ifTrue:[ |
2321 Processor signal:outputSema afterSeconds:timeout |
2474 Processor signal:outputSema afterSeconds:timeout |
2322 ]. |
2475 ]. |
2323 Processor signal:outputSema onOutput:fd. |
2476 Processor signal:outputSema onOutput:fd. |
2324 Processor activeProcess state:#ioWait. |
2477 Processor activeProcess state:#ioWait. |
2325 outputSema wait. |
2478 outputSema wait. |
2326 Processor disableSemaphore:outputSema. |
2479 Processor disableSemaphore:outputSema. |
2327 canWrite := OperatingSystem writeCheck:fd |
2480 canWrite := OperatingSystem writeCheck:fd |
2328 ]. |
2481 ]. |
2329 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2482 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2330 ^ canWrite |
2483 ^ canWrite |
2331 ! ! |
2484 ! ! |
2332 |
2485 |
2333 !ExternalStream methodsFor:'reimplemented for speed'! |
2486 !ExternalStream methodsFor:'reimplemented for speed'! |
2334 |
2487 |
2335 peekFor:anObject |
2488 peekFor:anObject |
2336 "return true and move past if next == something. |
2489 "return true and move past next element, if next == something. |
2337 Otherwise, stay and return false." |
2490 Otherwise, stay and return false. False is also returned |
|
2491 when EOF is encountered." |
2338 |
2492 |
2339 %{ /* NOCONTEXT */ |
2493 %{ /* NOCONTEXT */ |
2340 |
2494 |
2341 FILE *f; |
2495 FILE *f; |
2342 int c; |
2496 int c; |
2343 int peekValue; |
2497 int peekValue; |
2344 extern int _immediateInterrupt; |
2498 extern int _immediateInterrupt; |
2345 |
2499 |
2346 if (_INST(filePointer) != nil) { |
2500 _INST(lastErrorNumber) = nil; |
2347 if (_INST(binary) == true) { |
2501 if ((_INST(filePointer) != nil) |
2348 if (_isSmallInteger(anObject)) { |
2502 && (_INST(mode) != @symbol(writeonly))) { |
2349 peekValue = _intVal(anObject) & 0xFF; |
2503 if (_INST(binary) == true) { |
2350 } else { |
2504 if (_isSmallInteger(anObject)) { |
2351 goto bad; |
2505 peekValue = _intVal(anObject) & 0xFF; |
2352 } |
2506 } else { |
2353 } else { |
2507 goto bad; |
2354 if (__isCharacter(anObject)) { |
2508 } |
2355 peekValue = _intVal(_characterVal(anObject)) & 0xFF; |
2509 } else { |
2356 } else { |
2510 if (__isCharacter(anObject)) { |
2357 goto bad; |
2511 peekValue = _intVal(_characterVal(anObject)) & 0xFF; |
2358 } |
2512 } else { |
2359 } |
2513 goto bad; |
2360 |
2514 } |
2361 f = MKFD(_INST(filePointer)); |
2515 } |
2362 _immediateInterrupt = 1; |
2516 |
2363 c = getc(f); |
2517 if ((_INST(didWrite) != false) |
2364 _immediateInterrupt = 0; |
2518 && (_INST(mode) == @symbol(readwrite))) { |
2365 |
2519 _INST(didWrite) = false; |
2366 if (c == peekValue) { |
2520 fseek(f, 0L, 1); /* needed in stdio */ |
2367 OBJ pos; |
2521 } |
2368 |
2522 |
2369 if ((pos = _INST(position)) != nil) { |
2523 f = MKFD(_INST(filePointer)); |
2370 _INST(position) = _MKSMALLINT(_intVal(pos) + 1); |
2524 _immediateInterrupt = 1; |
2371 } |
2525 c = getc(f); |
2372 RETURN ( true ); |
2526 _immediateInterrupt = 0; |
2373 } |
2527 |
2374 |
2528 if (c == peekValue) { |
2375 if (c == EOF) { |
2529 OBJ pos; |
2376 _INST(hitEOF) = true; |
2530 |
2377 } else { |
2531 if ((pos = _INST(position)) != nil) { |
2378 ungetc(c, f); |
2532 _INST(position) = _MKSMALLINT(_intVal(pos) + 1); |
2379 } |
2533 } |
2380 RETURN ( false ); |
2534 RETURN (true); |
|
2535 } |
|
2536 |
|
2537 if (c != EOF) { |
|
2538 ungetc(c, f); |
|
2539 RETURN (false); |
|
2540 } |
|
2541 |
|
2542 if (ferror(f)) { |
|
2543 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
2544 } else { |
|
2545 _INST(hitEOF) = true; |
|
2546 RETURN (false); |
|
2547 } |
2381 } |
2548 } |
2382 bad: ; |
2549 bad: ; |
2383 %} |
2550 %}. |
2384 . |
2551 mode == #writeonly ifTrue:[^ self errorWriteOnly]. |
|
2552 lastErrorNumber notNil iftrue:[^ self readError]. |
2385 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2553 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2386 ^ super peekFor:anObject |
2554 ^ super peekFor:anObject |
2387 ! |
2555 ! |
2388 |
2556 |
2389 nextMatchFor:anObject |
2557 nextMatchFor:anObject |
2684 |
2880 |
2685 FILE *f; |
2881 FILE *f; |
2686 int c; |
2882 int c; |
2687 extern int _immediateInterrupt; |
2883 extern int _immediateInterrupt; |
2688 |
2884 |
2689 if ((_INST(filePointer) != nil) && (_INST(mode) != _writeonly)) { |
2885 _INST(lastErrorNumber) = nil; |
2690 if (_INST(binary) != true) { |
2886 if ((_INST(filePointer) != nil) |
2691 f = MKFD(_INST(filePointer)); |
2887 && (_INST(mode) != @symbol(writeonly))) { |
2692 |
2888 if (_INST(binary) != true) { |
2693 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
2889 f = MKFD(_INST(filePointer)); |
2694 _INST(didWrite) = false; |
2890 |
2695 fseek(f, 0L, 1); /* needed in stdio */ |
2891 if ((_INST(didWrite) != false) |
2696 } |
2892 && (_INST(mode) == @symbol(readwrite))) { |
2697 |
2893 _INST(didWrite) = false; |
2698 _immediateInterrupt = 1; |
2894 fseek(f, 0L, 1); /* needed in stdio */ |
2699 while (1) { |
2895 } |
|
2896 |
|
2897 _immediateInterrupt = 1; |
|
2898 while (1) { |
2700 |
2899 |
2701 if (feof(f)) { |
2900 if (feof(f)) { |
2702 _immediateInterrupt = 0; |
2901 _immediateInterrupt = 0; |
2703 RETURN ( nil ); |
2902 RETURN ( nil ); |
2704 } |
2903 } |
2705 |
2904 |
2706 c = getc(f); |
2905 c = getc(f); |
2707 |
2906 |
2708 switch (c) { |
2907 switch (c) { |
2709 case ' ': |
2908 case ' ': |
2710 case '\t': |
2909 case '\t': |
2711 case '\b': |
2910 case '\b': |
2712 break; |
2911 break; |
2713 |
2912 |
2714 default: |
2913 default: |
2715 if (c < 0) { |
2914 _immediateInterrupt = 0; |
2716 _INST(hitEOF) = true; |
2915 if (c < 0) { |
2717 _immediateInterrupt = 0; |
2916 if (ferror(f)) { |
2718 RETURN ( nil ); |
2917 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
2719 } |
2918 goto err; |
2720 ungetc(c, f); |
2919 } |
2721 _immediateInterrupt = 0; |
2920 _INST(hitEOF) = true; |
2722 RETURN ( _MKCHARACTER(c & 0xFF) ); |
2921 RETURN ( nil ); |
2723 } |
2922 } |
2724 } |
2923 ungetc(c, f); |
2725 } |
2924 RETURN ( _MKCHARACTER(c & 0xFF) ); |
2726 } |
2925 } |
2727 %} |
2926 } |
2728 . |
2927 } |
|
2928 } |
|
2929 err: ; |
|
2930 %}. |
|
2931 lastErrorNumber notNil iftrue:[^ self readError]. |
2729 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2932 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2730 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
2933 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
2731 self errorBinary |
2934 ^ self errorBinary |
|
2935 ! |
|
2936 |
|
2937 nextAlphaNumericWord |
|
2938 "read the next word (i.e. up to non letter-or-digit). |
|
2939 return a string containing those characters." |
|
2940 |
|
2941 %{ /* STACK: 2000 */ |
|
2942 FILE *f; |
|
2943 int len; |
|
2944 char buffer[1024]; |
|
2945 int ch; |
|
2946 int cnt = 0; |
|
2947 extern int _immediateInterrupt; |
|
2948 |
|
2949 if ((_INST(filePointer) != nil) |
|
2950 && (_INST(mode) != @symbol(writeonly))) { |
|
2951 f = MKFD(_INST(filePointer)); |
|
2952 |
|
2953 _immediateInterrupt = 1; |
|
2954 |
|
2955 if ((_INST(didWrite) != false) |
|
2956 && (_INST(mode) == @symbol(readwrite))) { |
|
2957 _INST(didWrite) = false; |
|
2958 fseek(f, 0L, 1); /* needed in stdio */ |
|
2959 } |
|
2960 |
|
2961 for (;;) { |
|
2962 ch = getc(f); |
|
2963 if (ch < 0) { |
|
2964 if (ferror(f)) { |
|
2965 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
2966 goto err; |
|
2967 } |
|
2968 _INST(hitEOF) = true; |
|
2969 break; |
|
2970 } |
|
2971 cnt++; |
|
2972 |
|
2973 if (ch >= ' ') break; |
|
2974 if ((ch != ' ') && (ch != '\t') && (ch != '\r') |
|
2975 && (ch != '\n') && (ch != 0x0b)) break; |
|
2976 } |
|
2977 ungetc(ch, f); |
|
2978 cnt--; |
|
2979 |
|
2980 len = 0; |
|
2981 for (;;) { |
|
2982 ch = getc(f); |
|
2983 if (ch < 0) { |
|
2984 if (ferror(f)) { |
|
2985 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
2986 goto err; |
|
2987 } |
|
2988 _INST(hitEOF) = true; |
|
2989 break; |
|
2990 } |
|
2991 |
|
2992 ch &= 0xFF; |
|
2993 if (! (((ch >= 'a') && (ch <= 'z')) || |
|
2994 ((ch >= 'A') && (ch <= 'Z')) || |
|
2995 ((ch >= '0') && (ch <= '9')))) { |
|
2996 ungetc(ch, f); |
|
2997 break; |
|
2998 } |
|
2999 cnt++; |
|
3000 buffer[len++] = ch; |
|
3001 if (len >= sizeof(buffer)-1) { |
|
3002 /* emergency */ |
|
3003 break; |
|
3004 } |
|
3005 } |
|
3006 _immediateInterrupt = 0; |
|
3007 |
|
3008 if (_INST(position) != nil) { |
|
3009 _INST(position) = _MKSMALLINT(_intVal(_INST(position)) + cnt); |
|
3010 } |
|
3011 buffer[len] = '\0'; |
|
3012 if (len != 0) { |
|
3013 RETURN ( _MKSTRING(buffer COMMA_CON) ); |
|
3014 } |
|
3015 RETURN ( nil ); |
|
3016 } |
|
3017 err: ; |
|
3018 %}. |
|
3019 lastErrorNumber notNil ifTrue:[^ self readError]. |
|
3020 filePointer isNil ifTrue:[^ self errorNotOpen]. |
|
3021 ^ self errorWriteOnly |
2732 ! |
3022 ! |
2733 |
3023 |
2734 nextChunk |
3024 nextChunk |
2735 "return the next chunk, i.e. all characters up to the next |
3025 "return the next chunk, i.e. all characters up to the next |
2736 non-doubled exclamation mark; undouble doubled exclamation marks. |
3026 non-doubled exclamation mark; undouble doubled exclamation marks. |
2737 - reimplemented for speed" |
3027 - reimplemented for speed" |
2738 |
3028 |
2739 |retVal| |
3029 |retVal| |
2740 |
3030 |
2741 filePointer isNil ifTrue:[ |
3031 filePointer isNil ifTrue:[^ self errorNotOpen]. |
2742 ^ self errorNotOpen |
3032 binary ifTrue:[^ self errorBinary]. |
2743 ]. |
3033 (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. |
2744 binary ifTrue:[ |
|
2745 ^ self errorBinary |
|
2746 ]. |
|
2747 |
|
2748 %{ |
3034 %{ |
2749 FILE *f; |
3035 FILE *f; |
2750 int done = 0; |
3036 int done = 0; |
2751 REGISTER int c; |
3037 REGISTER int c; |
2752 unsigned char peekC; |
3038 unsigned char peekC; |
2753 char *buffer, *newBuffer; |
3039 char *buffer = (char *)0, *newBuffer; |
2754 REGISTER int index; |
3040 REGISTER int index; |
2755 int currSize; |
3041 int currSize; |
2756 int inComment, inString, inPrimitive = 0; |
3042 int inComment, inString, inPrimitive = 0; |
2757 extern int _immediateInterrupt; |
3043 extern int _immediateInterrupt; |
2758 |
3044 |
|
3045 _INST(lastErrorNumber) = nil; |
2759 f = MKFD(_INST(filePointer)); |
3046 f = MKFD(_INST(filePointer)); |
2760 |
3047 |
2761 if ((_INST(didWrite) != false) && (_INST(mode) == _readwrite)) { |
3048 if ((_INST(didWrite) != false) |
2762 _INST(didWrite) = false; |
3049 && (_INST(mode) == @symbol(readwrite))) { |
2763 fseek(f, 0L, 1); /* needed in stdio */ |
3050 _INST(didWrite) = false; |
|
3051 fseek(f, 0L, 1); /* needed in stdio */ |
|
3052 } |
|
3053 |
|
3054 if (feof(f)) { |
|
3055 _immediateInterrupt = 0; |
|
3056 RETURN (nil); |
2764 } |
3057 } |
2765 |
3058 |
2766 /* |
3059 /* |
2767 * skip spaces |
3060 * skip spaces |
2768 */ |
3061 */ |
2769 _immediateInterrupt = 1; |
3062 _immediateInterrupt = 1; |
2770 while (! done) { |
3063 while (! done) { |
2771 if (feof(f)) { |
3064 |
2772 _immediateInterrupt = 0; |
3065 do { |
2773 RETURN ( nil ); |
3066 c = getc(f); |
2774 } |
3067 } while ((c < 0) && (errno == EINTR)); |
2775 |
3068 |
2776 do { |
3069 switch (c) { |
2777 c = getc(f); |
3070 case ' ': |
2778 } while ((c < 0) && (errno == EINTR)); |
3071 case '\t': |
2779 |
3072 case '\n': |
2780 switch (c) { |
3073 case '\r': |
2781 case ' ': |
3074 case '\b': |
2782 case '\t': |
3075 case '\014': |
2783 case '\n': |
3076 break; |
2784 case '\r': |
3077 |
2785 case '\b': |
3078 case EOF: |
2786 case '\014': |
3079 _immediateInterrupt = 0; |
2787 break; |
3080 if (ferror(f)) { |
2788 |
3081 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
2789 case EOF: |
3082 goto err; |
2790 _immediateInterrupt = 0; |
3083 } |
2791 _INST(hitEOF) = true; |
3084 _INST(hitEOF) = true; |
2792 RETURN ( nil ); |
3085 RETURN (nil); |
2793 |
3086 |
2794 default: |
3087 default: |
2795 ungetc(c, f); |
3088 ungetc(c, f); |
2796 done = 1; |
3089 done = 1; |
2797 break; |
3090 break; |
2798 } |
3091 } |
2799 } |
3092 } |
2800 |
3093 |
2801 /* |
3094 /* |
2802 * read chunk into a buffer |
3095 * read chunk into a buffer |
2803 */ |
3096 */ |
2804 buffer = (char *)malloc(3000); |
3097 buffer = (char *)malloc(3000); |
2805 currSize = 3000; |
3098 currSize = 3000; |
2806 index = 0; |
3099 index = 0; |
2807 while (! feof(f)) { |
3100 while (! feof(f)) { |
2808 /* do we have to resize the buffer ? */ |
3101 /* do we have to resize the buffer ? */ |
2809 if ((index+2) >= currSize) { |
3102 if ((index+2) >= currSize) { |
2810 newBuffer = (char *)malloc(currSize * 2); |
3103 newBuffer = (char *)malloc(currSize * 2); |
2811 bcopy(buffer, newBuffer, index); |
3104 bcopy(buffer, newBuffer, index); |
2812 free(buffer); |
3105 free(buffer); |
2813 buffer = newBuffer; |
3106 buffer = newBuffer; |
2814 currSize = currSize * 2; |
3107 currSize = currSize * 2; |
2815 } |
3108 } |
2816 do { |
3109 do { |
2817 c = getc(f); |
3110 c = getc(f); |
2818 } while (c < 0 && (errno == EINTR)); |
3111 } while (c < 0 && (errno == EINTR)); |
2819 |
3112 |
2820 if (c == '%') { |
3113 if (c == '%') { |
2821 peekC = getc(f); |
3114 peekC = getc(f); |
2822 ungetc(peekC, f); |
3115 ungetc(peekC, f); |
2823 if (peekC == '{') { |
3116 if (peekC == '{') { |
2824 inPrimitive++; |
3117 inPrimitive++; |
2825 } else if (peekC == '}') { |
3118 } else if (peekC == '}') { |
2826 inPrimitive--; |
3119 inPrimitive--; |
2827 } |
3120 } |
2828 } else { |
3121 } else { |
2829 if (! inPrimitive) { |
3122 if (! inPrimitive) { |
2830 if (c == '!') { |
3123 if (c == '!') { |
2831 do { |
3124 do { |
2832 c = getc(f); |
3125 c = getc(f); |
2833 } while (c < 0 && (errno == EINTR)); |
3126 } while (c < 0 && (errno == EINTR)); |
2834 if (c != '!') { |
3127 if (c != '!') { |
2835 ungetc(c, f); |
3128 ungetc(c, f); |
2836 break; |
3129 break; |
2837 } |
3130 } |
2838 } |
3131 } |
2839 } |
3132 } |
2840 } |
3133 } |
2841 if (c == EOF) { |
3134 |
2842 _INST(hitEOF) = true; |
3135 if (c < 0) { |
2843 break; |
3136 _immediateInterrupt = 0; |
2844 } |
3137 if (ferror(f)) { |
2845 buffer[index++] = c; |
3138 _INST(lastErrorNumber) = _MKSMALLINT(errno); |
|
3139 goto err; |
|
3140 } |
|
3141 _INST(hitEOF) = true; |
|
3142 break; |
|
3143 } |
|
3144 buffer[index++] = c; |
2846 } |
3145 } |
2847 _immediateInterrupt = 0; |
3146 _immediateInterrupt = 0; |
2848 |
3147 |
2849 buffer[index] = '\0'; |
3148 buffer[index] = '\0'; |
2850 /* |
3149 /* |
2851 * make it a string |
3150 * make it a string |
2852 */ |
3151 */ |
2853 retVal = _MKSTRING(buffer COMMA_CON); |
3152 retVal = _MKSTRING(buffer COMMA_CON); |
2854 free(buffer); |
3153 err: |
2855 %} |
3154 if (buffer) |
2856 . |
3155 free(buffer); |
|
3156 %}. |
|
3157 lastErrorNumber notNil ifTrue:[^ self readError]. |
2857 ^ retVal |
3158 ^ retVal |
2858 ! ! |
3159 ! ! |