; ; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap); ; /* Standard C function */ ; ; 2004-11-28, Ullrich von Bassewitz ; 2014-09-10, Greg King ; .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 = d->str[d->index]; ; if (C == '\0') { ; return EOF; ; } ; /* Increment index only if end not reached */ ; ++d->index; ; return C; ; } ; .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 #<-1 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 #<$0001 sta (ptr1),y iny lda (ptr1),y adc #>$0001 sta (ptr1),y ; Return the char just read txa ldx #>$0000 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 #<$0001 sta (ptr1),y iny lda (ptr1),y sbc #>$0001 sta (ptr1),y ; Return c jmp popax .endproc ; ---------------------------------------------------------------------------- ; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap) ; /* Standard C function */ ; { ; /* Initialize the data structs. The sscanfdata struct will be passed back ; ** to the get and unget functions by _scanf(). ; */ ; static struct sscanfdata sd; ; static const struct scanfdata d = { ; ( getfunc) get, ; (ungetfunc) unget, ; (void*) &sd ; }; ; ; sd.str = str; ; sd.index = 0; ; ; /* Call the internal function and return the result */ ; return _scanf (&d, format, ap); ; } ; .bss sd: .tag SSCANFDATA .rodata 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 lda #$00 sta sd + SSCANFDATA::INDEX sta sd + SSCANFDATA::INDEX+1 ; Restore the low byte of ap, and jump to _scanf() which will clean up the stack pla jmp __scanf .endproc