X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libsrc%2Fcommon%2Ffread.s;h=91d69298539d65fa5be31664da0ce46235177740;hb=959eff34a3c21673f043005c92d46549e9f0e726;hp=bcad7f9b7374660f3c81605abad92c557aa9247a;hpb=8070250984f7cbea0d389b3dc9d05d96371f628a;p=cc65 diff --git a/libsrc/common/fread.s b/libsrc/common/fread.s index bcad7f9b7..91d692985 100644 --- a/libsrc/common/fread.s +++ b/libsrc/common/fread.s @@ -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 @@ -70,66 +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 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 @@ -138,5 +208,6 @@ ; Data .bss -f: .res 2 +save: .res 2 +pb: .res 1