]> git.sur5r.net Git - cc65/blobdiff - libsrc/common/fread.s
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / libsrc / common / fread.s
index bcad7f9b7374660f3c81605abad92c557aa9247a..91d69298539d65fa5be31664da0ce46235177740 100644 (file)
@@ -1,67 +1,90 @@
 ;
-; Ullrich von Bassewitz, 22.11.2002
+; Ullrich von Bassewitz, 2002-11-22, 2004-05-14
 ;
-; size_t __fastcall__ fread (void* buf, size_t size, size_t count, FILE* f);
+; size_t __fastcall__ fread (void* buf, size_t size, size_t count, FILE* file);
 ; /* Read from a file */
 ;
 
         .export         _fread
 
         .import         _read
-        .import         pushax, incsp6, addysp, ldaxysp, pushwysp, return0
+        .import         pusha0, pushax
+        .import         incsp4, incsp6
+        .import         ldaxysp, ldax0sp
+        .import         pushwysp
         .import         tosumulax, tosudivax
 
-        .importzp       ptr1, tmp1
+        .importzp       ptr1, sp
 
         .include        "errno.inc"
         .include        "_file.inc"
 
+        .macpack        generic
 
 ; ------------------------------------------------------------------------
 ; Code
 
 .proc   _fread
 
-; Save f and place it into ptr1
+; We will place a pointer to the file descriptor into the register bank
 
-       sta     f
-       sta     ptr1
-       stx     f+1
-       stx     ptr1+1
+        .import regbank: zp
+        file    = regbank
 
-; Check if the file is open
+; Save two bytes from the register bank
+
+        ldy     file+0
+        sty     save
+        ldy     file+1
+        sty     save+1
 
-       ldy     #_FILE_f_flags
-       lda     (ptr1),y
-       and     #_FOPEN                 ; Is the file open?
-               bne     @L2                     ; Branch if yes
+; Save the file pointer into the register bank
 
-; File not open
+        sta     file
+        stx     file+1
+
+; Check if the file is open
 
-       lda     #EINVAL
-       sta     __errno
-       lda     #0
-       sta     __errno+1
-@L1:    jsr     incsp6
-        jmp     return0
+        ldy     #_FILE::f_flags
+        lda     (file),y
+        and     #_FOPEN                 ; Is the file open?
+        beq     @L1                     ; Branch if no
 
 ; Check if the stream is in an error state
 
-@L2:   lda     (ptr1),y                ; get f->f_flags again
-       and     #_FERROR
-       bne     @L1
+        lda     (file),y                ; get file->f_flags again
+        and     #_FERROR
+        beq     @L2
+
+; File not open or in error state
+
+@L1:    lda     #EINVAL
+        jsr     __seterrno              ; Set __errno, return zero in A
+        tax                             ; a/x = 0
+        jmp     @L99                    ; Bail out
+
+; Remember if we have a pushed back character and reset the flag.
+
+@L2:    tax                             ; X = 0
+        lda     (file),y
+        and     #_FPUSHBACK
+        beq     @L3
+        lda     (file),y
+        and     #<~_FPUSHBACK
+        sta     (file),y                ; file->f_flags &= ~_FPUSHBACK;
+        inx                             ; X = 1
+@L3:    stx     pb
 
 ; Build the stackframe for read()
 
-        ldy     #_FILE_f_fd
-        lda     (ptr1),y
-        ldx     #$00
-        jsr     pushax                  ; f->f_fd
+        ldy     #_FILE::f_fd
+        lda     (file),y
+        jsr     pusha0                  ; file->f_fd
 
         ldy     #9
         jsr     pushwysp                ; buf
 
-; Stack is now: buf/size/count/f->fd/buf
+; Stack is now: buf/size/count/file->fd/buf
 ; Calculate the number of bytes to read: count * size
 
         ldy     #7
         jsr     ldaxysp                 ; Get size
         jsr     tosumulax               ; count * size -> a/x
 
-; Check if the number of bytes is zero. Don't call read in this case
+; Check if count is zero.
 
-        cpx     #0
-        bne     @L3
         cmp     #0
-        bne     @L3
+        bne     @L4
+        cpx     #0
+        bne     @L4
 
-; The number of bytes to read is zero, just return count
+; Count is zero, drop the stack frame just built and return count
 
-        ldy     #5
-        jsr     ldaxysp                 ; Get count
-        ldy     #10
-        jmp     addysp                  ; Drop params, return
+        jsr     incsp4                  ; Drop file->fd/buf
+        jsr     ldax0sp                 ; Get count
+        jmp     @L99                    ; Bail out
+
+; Check if we have a buffered char from ungetc
+
+@L4:    ldy     pb
+        beq     @L6
+
+; We have a buffered char from ungetc. Save the low byte from count
+
+        pha
+
+; Copy the buffer pointer into ptr1, and increment the pointer value passed
+; to read() by one, so read() starts to store data at buf+1.
+
+        ldy     #0
+        lda     (sp),y
+        sta     ptr1
+        add     #1
+        sta     (sp),y
+        iny
+        lda     (sp),y
+        sta     ptr1+1
+        adc     #0
+        sta     (sp),y                  ; ptr1 = buf++;
+
+; Get the buffered character and place it as first character into the read
+; buffer.
+
+        ldy     #_FILE::f_pushback
+        lda     (file),y
+        ldy     #0
+        sta     (ptr1),y                ; *buf = file->f_pushback;
+
+; Restore the low byte of count and decrement count by one. This may result
+; in count being zero, so check for that.
+
+        pla
+        sub     #1
+        bcs     @L5
+        dex
+@L5:    cmp     #0
+        bne     @L6
+        cpx     #0
+        beq     @L8
 
 ; Call read(). This will leave the original 3 params on the stack
 
-@L3:    jsr     pushax
-        jsr     _read
+@L6:    jsr     _read
 
 ; Check for errors in read
 
         cpx     #$FF
-        bne     @L5
+        bne     @L8
         cmp     #$FF
-        bne     @L5
+        bne     @L8
 
-; Error in read. Set the stream error flag and bail out. _oserror and/or
-; errno are already set by read().
+; Error in read. Set the stream error flag and bail out. errno has already
+; been set by read(). On entry to label @L7, X must be zero. 
 
+        inx                             ; X = 0
         lda     #_FERROR
-@L4:    sta     tmp1
-        lda     f
-        sta     ptr1
-        lda     f+1
-        sta     ptr1+1
-        ldy     #_FILE_f_flags
-        lda     (ptr1),y
-        ora     tmp1
-        sta     (ptr1),y
-        bne     @L1                     ; Return zero
+@L7:    ldy     #_FILE::f_flags         ; X must be zero here!
+        ora     (file),y
+        sta     (file),y
+        txa                             ; a/x = 0
+        beq     @L99                    ; Return zero
 
-; Read was ok, check for end of file.
+; Read was ok, account for the pushed back character (if any).
 
-@L5:    cmp     #0                      ; Zero bytes read?
-        bne     @L6
+@L8:    add     pb
+        bcc     @L9
+        inx
+
+; Check for end of file.
+
+@L9:    cmp     #0                      ; Zero bytes read?
+        bne     @L10
         cpx     #0
-        bne     @L6
+        bne     @L10
 
 ; Zero bytes read. Set the EOF flag
 
         lda     #_FEOF
-        bne     @L4                     ; Set flag and return zero
+        bne     @L7                     ; Set flag and return zero
 
 ; Return the number of items successfully read. Since we've checked for
 ; bytes == 0 above, size cannot be zero here, so the division is safe.
 
-@L6:    jsr     pushax                  ; Push number of bytes read
+@L10:   jsr     pushax                  ; Push number of bytes read
         ldy     #5
         jsr     ldaxysp                 ; Get size
         jsr     tosudivax               ; bytes / size -> a/x
+@L99:   ldy     save                    ; Restore zp register
+        sty     file
+        ldy     save+1
+        sty     file+1
         jmp     incsp6                  ; Drop params, return
 
 .endproc
 ; Data
 
 .bss
-f:     .res    2
+save:   .res    2
+pb:     .res    1