From 1d7884fa94cbeeb3e97cdb18e8bc6a6963e2756d Mon Sep 17 00:00:00 2001 From: cuz Date: Fri, 14 May 2004 20:54:46 +0000 Subject: [PATCH] Add support for pushed back characters from ungetc() git-svn-id: svn://svn.cc65.org/cc65/trunk@3043 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/common/fread.s | 182 +++++++++++++++++++++++++++++------------- 1 file changed, 128 insertions(+), 54 deletions(-) diff --git a/libsrc/common/fread.s b/libsrc/common/fread.s index e65f33bea..1a5434420 100644 --- a/libsrc/common/fread.s +++ b/libsrc/common/fread.s @@ -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 + +; Save two bytes from the register bank + + ldy file+0 + sty save + ldy file+1 + sty save+1 + +; Save the file pointer into the register bank + + sta file + stx file+1 ; Check if the file is open - ldy #_FILE::f_flags - lda (ptr1),y - and #_FOPEN ; Is the file open? - bne @L2 ; Branch if yes - -; File not 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 @@ -68,65 +93,113 @@ 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 @@ -135,5 +208,6 @@ ; Data .bss -file: .res 2 +save: .res 2 +pb: .res 1