;
-; Christian Groessler, Apr-2000
+; Christian Groessler, May-2004
;
; int __fastcall__ read(int fd,void *buf,int count)
;
beq done ; if size 0, it's a no-op
cpx #$FF ; invalid iocb?
beq _inviocb
+
+.ifdef LINEBUF
+ ; E: should be always at IOCB #0
+ ; fixme: what happens when user closes and reopens stdin?
+ cpx #0 ; E: handler (line oriented keyboard input)?
+ beq do_line
+.endif
+
lda #GETCHR ; iocb command code
sta ICCOM,x
jsr CIOV ; read it
pha ; save
lda ICBLH,x ; get buf len hi
tax ; to X
- lda #0
+okdone: lda #0
sta __oserror ; clear system dependend error code
pla ; get buf len lo
rts
_inviocb:
jmp __inviocb
+
+
+.ifdef LINEBUF
+
+; line oriented input
+
+do_line:
+ lda buflen ; line buffer active?
+ bne use_buf ; yes, get data from there
+
+ ; save user buffer address & length
+ ; update IOCB to point to line buffer
+ lda ICBLL,x
+ pha
+ lda #LINEBUF
+ sta ICBLL,x
+ ;--------
+ lda ICBLH,x
+ pha
+ lda #0
+ sta ICBLH,x
+ ;--------
+ lda ICBAL,x
+ pha
+ lda #<linebuf
+ sta ICBAL,x
+ ;--------
+ lda ICBAH,x
+ pha
+ lda #>linebuf
+ sta ICBAH,x
+
+ lda #GETREC
+ sta ICCOM,x
+ jsr CIOV ; read input data
+ bpl newbuf
+ cpy #EOFERR ; eof is treated specially
+ beq newbuf
+ pla ; fix stack
+ pla
+ pla
+ pla
+ jmp __do_oserror ; update errno
+
+newbuf:
+ lda ICBLL,x ; get # of bytes read
+ sta buflen
+ lda #0
+ sta index
+
+ ; restore user buffer address & length
+ pla
+ sta ICBAH,x
+ ;--------
+ pla
+ sta ICBAL,x
+ ;--------
+ pla
+ sta ICBLH,x
+ ;--------
+ pla
+ sta ICBLL,x
+
+ ; fall into use_buf
+
+; return bytes from line buffer
+; use buflen and index to access buffer
+; update index
+; use dataptr as a temporary pointer
+
+use_buf:
+ lda buflen
+ sec
+ sbc index ; size of unread data in the buffer
+ sta cbs
+
+ lda ICBLL,x ; buf len lo
+ cmp cbs ; larger than buffer size?
+ beq bl1
+ bcs btsmall ; yes, adjust length
+
+bl1: lda ICBLH,x ; get buf len hi
+ bne btsmall ; buffer too small: buffer contents < read size
+
+; copy ICBLL,x bytes
+
+icbll_copy:
+
+ lda ICBAL,x ; buffer address
+ sta dataptr
+ lda ICBAH,x ; buffer address
+ sta dataptr+1
+ lda ICBLL,x
+ sta copylen
+ pha ; remember for return value
+ ldy #0
+ ldx index
+
+copy: lda linebuf,x
+ sta (dataptr),y
+ iny
+ inx
+ dec copylen
+ bne copy
+
+ pla ; length
+ pha ; save length to return at okdone
+
+ clc
+ adc index
+ sta index
+ cmp buflen ; buffer used up?
+ bcc c1 ; not yet
+
+ lda #0
+ sta buflen ; indicate empty line buffer
+
+c1: ldx #0
+ jmp okdone ; return to caller
+
+btsmall:
+ lda cbs
+ sta ICBLL,x
+ bne icbll_copy
+
+; brk ; not reached
+
+ .zeropage
+
+index: .res 1 ; index into line buffer
+buflen: .res 1 ; length of used part of buffer
+cbs: .res 1 ; current buffer size: buflen - index
+dataptr:.res 2 ; temp pointer to user buffer
+copylen:.res 1 ; temp counter
+
+ .bss
+
+linebuf:.res LINEBUF ; the line buffer
+
+.endif ; .ifdef LINEBUF
+