1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-18 00:07:21 +00:00
cc65/libsrc/common/vfscanf.s
cuz d406a9f677 Scanf improvements by Greg King
git-svn-id: svn://svn.cc65.org/cc65/trunk@3377 b7a2c559-68d2-44c3-8de9-860c34a00d81
2005-02-14 09:19:59 +00:00

99 lines
2.4 KiB
ArmAsm

;
; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap);
;
; 2004-11-27, Ullrich von Bassewitz
; 2004-12-21, Greg King
;
.export _vfscanf
.import _fgetc, _ungetc, _ferror
.include "zeropage.inc"
.include "_scanf.inc"
.include "stdio.inc"
count := ptr3 ; Result of scan
; ----------------------------------------------------------------------------
; Static scanfdata structure for the _vfscanf routine
;
.data
d: .addr _fgetc ; GET
.addr _ungetc ; UNGET
.addr 0 ; data
; ----------------------------------------------------------------------------
; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap)
; /* Standard C function */
; {
; /* Initialize the data struct. We do only need the given file as user data,
; * because the (getfunc) and (ungetfunc) functions are crafted so that they
; * match the standard-I/O fgetc() and ungetc().
; */
; static struct scanfdata d = {
; ( getfunc) fgetc,
; (ungetfunc) ungetc
; };
; static int count;
;
; d.data = (void*) f;
;
; /* Call the internal function */
; count = _scanf (&d, format, ap);
;
; /* And, return the result */
; return ferror (f) ? EOF : count;
; }
;
; Because _scanf() has the same parameter stack as vfscanf(), with f replaced
; by &d, we will do exactly that. _scanf() then will clean up the stack.
; Beware: Since ap is a fastcall parameter, we must not destroy a/x.
;
.code
_vfscanf:
pha ; Save low byte of ap
; Swap f against &d on the stack, placing f into d.data
ldy #2 ; Offset of f on the stack
lda (sp),y
sta d + SCANFDATA::DATA
lda #<d
sta (sp),y
iny ; High byte
lda (sp),y
sta d + SCANFDATA::DATA + 1
lda #>d
sta (sp),y
; Restore the low byte of ap, and call the _scanf function
pla
jsr __scanf
sta count
stx count+1
; Return -1 if there was a read error during the scan
lda d + SCANFDATA::DATA ; Get f
ldx d + SCANFDATA::DATA+1
jsr _ferror
tay
beq L1
lda #<EOF
tax
rts
; Or, return the result of the scan
L1: lda count
ldx count+1
rts