]> git.sur5r.net Git - cc65/blobdiff - libsrc/atari/read.s
The spans do now contain the size of a span, no longer the end offset.
[cc65] / libsrc / atari / read.s
index ef16ae8cef34c9d0907ca4410a08879fbadacc1e..19d33cb66d51c9b07aeb8c5e30911d4a1068bfd8 100644 (file)
@@ -1,5 +1,5 @@
 ;
-; Christian Groessler, Apr-2000
+; Christian Groessler, Jul-2005
 ;
 ; int __fastcall__ read(int fd,void *buf,int count)
 ;
        .import __rwsetup,__do_oserror,__inviocb,__oserror
        .export _read
 
-_read: jsr     __rwsetup       ; do common setup for read and write
-       beq     done            ; if size 0, it's a no-op
-       cpx     #$FF            ; invalid iocb?
-       beq     _inviocb
-       lda     #GETCHR         ; iocb command code
+_read: jsr     __rwsetup       ; do common setup for read and write
+       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
+       bpl     done
+       cpy     #EOFERR         ; eof is treated specially
+       beq     done
+       jmp     __do_oserror    ; update errno
+
+done:  lda     ICBLL,x         ; buf len lo
+       pha                     ; save
+       lda     ICBLH,x         ; get buf len hi
+       tax                     ; to X
+okdone:        lda     #0
+       sta     __oserror       ; clear system dependend error code
+       pla                     ; get buf len lo
+       rts
+
+_inviocb:
+       jmp     __inviocb
+
+
+.ifdef LINEBUF
+
+; line oriented input
+
+       .segment        "EXTZP" : 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
+
+        .code
+
+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 it
-       bpl     done
+       jsr     CIOV            ; read input data
+       bpl     newbuf
        cpy     #EOFERR         ; eof is treated specially
-       beq     done
+       beq     newbuf
+       pla                     ; fix stack
+       pla
+       pla
+       pla
        jmp     __do_oserror    ; update errno
 
-done:  lda     ICBLL,x         ; buf len lo
-       pha                     ; save
-       lda     ICBLH,x         ; get buf len hi
-       tax                     ; to X
+newbuf:
+       lda     ICBLL,x         ; get # of bytes read
+       sta     buflen
+       lda     #0
+       sta     index           ; fresh buffer
+
+       ; 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
+       lda     buflen
+
+; return bytes from line buffer
+; use buflen and index to access buffer
+; update index
+; use dataptr as a temporary pointer
+
+use_buf:
+       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     __oserror       ; clear system dependend error code
-       pla                     ; get buf len lo
-       rts
+       sta     buflen          ; indicate empty line buffer
+
+c1:    ldx     #0
+       jmp     okdone          ; return to caller
+
+btsmall:
+       lda     cbs
+       sta     ICBLL,x
+       bpl     icbll_copy
+
+.endif         ; .ifdef LINEBUF
 
-_inviocb:
-       jmp     __inviocb