1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-22 17:29:34 +00:00
cc65/libsrc/common/vsscanf.s

188 lines
4.1 KiB
ArmAsm
Raw Normal View History

;
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap);
; /* Standard C function */
;
; Ullrich von Bassewitz, 2004-11-28
;
.export _vsscanf
.import popax, __scanf
.importzp sp, ptr1, ptr2
.macpack generic
; ----------------------------------------------------------------------------
; Structure used to pass data to the callback functions
.struct SSCANFDATA
STR .addr
INDEX .word
.endstruct
; ----------------------------------------------------------------------------
; static int __fastcall__ get (struct sscanfdata* d)
; /* Read a character from the input string and return it */
; {
; char C;
; if (C = d->str[d->index]) {
; /* Increment index only if end not reached */
; ++d->index;
; return C;
; } else {
; return EOF;
; }
; }
;
.code
.proc get
sta ptr1
stx ptr1+1 ; Save d
; Get d->str adding the high byte of index to the pointer, so we can access
; the byte in the string with just the low byte as index
ldy #SSCANFDATA::STR
lda (ptr1),y
sta ptr2
iny
lda (ptr1),y
ldy #SSCANFDATA::INDEX+1
add (ptr1),y
sta ptr2+1
; Load the low byte of the index and fetch the byte from the string
dey ; = SSCANFDATA::INDEX
lda (ptr1),y
tay
lda (ptr2),y
; Return EOF if we are at the end of the string
bne L1
lda #$FF
tax
rts
; Bump the index (beware: A contains the char we must return)
L1: tax ; Save return value
tya ; Low byte of index
ldy #SSCANFDATA::INDEX
add #1
sta (ptr1),y
iny
lda (ptr1),y
adc #$00
sta (ptr1),y
; Return the char just read
txa
ldx #$00
rts
.endproc
; ----------------------------------------------------------------------------
; static int __fastcall__ unget (int c, struct sscanfdata* d)
; /* Push back a character onto the input stream */
; {
; /* We do assume here that the _scanf routine will not push back anything
; * not read, so we can ignore c safely and won't check the index.
; */
; --d->index;
; return c;
; }
;
.code
.proc unget
sta ptr1
stx ptr1+1 ; Save d
; Decrement the index
ldy #SSCANFDATA::INDEX
lda (ptr1),y
sub #1
sta (ptr1),y
iny
lda (ptr1),y
sbc #0
sta (ptr1),y
; Return c
jmp popax
.endproc
; ----------------------------------------------------------------------------
; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap)
; /* Standard C function */
; {
; struct sscanfdata sd;
; struct scanfdata d;
;
; /* Initialize the data structs. The sscanfdata struct will be passed back
; * to the get and unget functions by _scanf.
; */
; d.get = (getfunc) get;
; d.unget = (ungetfunc) unget,
; d.data = &sd;
; sd.str = str;
; sd.index = 0;
;
; /* Call the internal function and return the result */
; return _scanf (&d, format, ap);
; }
;
.data
sd: .tag SSCANFDATA
d: .addr get
.addr unget
.addr sd
.code
.proc _vsscanf
; Save the low byte of ap (which is passed in a/x)
pha
; Initialize sd and at the same time replace str on the stack by a pointer
; to d
ldy #2 ; Stack offset of str
lda (sp),y
sta sd + SSCANFDATA::STR
lda #<d
sta (sp),y
iny
lda (sp),y
sta sd + SSCANFDATA::STR+1
lda #>d
sta (sp),y
lda #$00
sta sd + SSCANFDATA::INDEX
sta sd + SSCANFDATA::INDEX+1
; Restore the low byte of ap and jump to _scanf which will cleanup the stacl
pla
jmp __scanf
.endproc