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:
parent
556b861640
commit
1d7884fa94
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user