+++ /dev/null
-/*
- * vsscanf.c
- *
- * (C) Copyright 2002 Ullrich von Bassewitz (uz@cc65.org)
- *
- */
-
-
-
-#include <stdio.h>
-#include "_scanf.h"
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-struct sscanfdata {
- const char* str; /* Pointer to input string */
- unsigned index; /* Read index */
-};
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-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;
- }
-}
-
-
-
-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;
-}
-
-
-
-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);
-}
-
-
-
--- /dev/null
+;
+; 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
+
+