1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-22 12:30:41 +00:00

Add support for pushed back characters from ungetc()

git-svn-id: svn://svn.cc65.org/cc65/trunk@3043 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2004-05-14 20:54:46 +00:00
parent 556b861640
commit 1d7884fa94

View 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
; 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