]> git.sur5r.net Git - cc65/commitdiff
Add support for pushed back characters from ungetc()
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 14 May 2004 20:54:46 +0000 (20:54 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 14 May 2004 20:54:46 +0000 (20:54 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3043 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/common/fread.s

index e65f33bea14053d507701d3be63a7b7daa4795e3..1a543442013a941477763cb99f394faae163ea46 100644 (file)
@@ -1,5 +1,5 @@
 ;
-; 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* file);
 ; /* Read from a file */
@@ -8,53 +8,78 @@
         .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 file and place it into ptr1
+; We will place a pointer to the file descriptor into the register bank
 
-       sta     file
-       sta     ptr1
-       stx     file+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
-        jsr     __seterrno
-@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 file->f_flags again
+        lda    (file),y                ; get file->f_flags again
        and     #_FERROR
-       bne     @L1
+       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                  ; file->f_fd
+        lda     (file),y
+        jsr     pusha0                  ; file->f_fd
 
         ldy     #9
         jsr     pushwysp                ; buf
         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     _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().
+; errno are already set by read(). On entry to label @L7, X must be zero.
 
+        inx                             ; X = 0
         lda     #_FERROR
-@L4:    sta     tmp1
-        lda     file
-        sta     ptr1
-        lda     file+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
-file:          .res    2
+save:          .res    2
+pb:     .res    1