; ; int vsnprintf (char* Buf, size_t size, const char* Format, va_list ap); ; ; Ullrich von Bassewitz, 2009-09-26 ; .export _vsnprintf .import ldaxysp, popax, incsp2, incsp6 .import _memcpy, __printf .importzp sp, ptr1 .macpack generic .data ; ---------------------------------------------------------------------------- ; ; Static data for the _vsnprintf routine ; outdesc: ; Static outdesc structure .word 0 ; ccount .word out ; Output function pointer .word 0 ; ptr .word 0 ; Buffer size .code ; ---------------------------------------------------------------------------- ; Callback routine used for the actual output. ; ; static void out (struct outdesc* d, const char* buf, unsigned count) ; /* Routine used for writing */ ; ; Since we know, we're called with a pointer to our static outdesc structure, ; we don't need the pointer passed on the stack. out: ; Calculate the space left in the buffer. If no space is left, don't copy ; any characters lda outdesc+6 ; Low byte of buffer size sec sbc outdesc+0 ; Low byte of bytes already written sta ptr1 lda outdesc+7 sbc outdesc+1 sta ptr1+1 bcs @L0 ; Space left lda #0 sta ptr1 sta ptr1+1 ; Replace the pointer to d by a pointer to the write position in the buffer ; for the call to memcpy that follows. @L0: lda outdesc+0 clc adc outdesc+4 ldy #4 sta (sp),y lda outdesc+1 adc outdesc+5 iny sta (sp),y ; Get Count from stack jsr popax ; outdesc.ccount += Count; pha clc adc outdesc+0 sta outdesc+0 txa adc outdesc+1 sta outdesc+1 pla ; if (Count > Left) Count = Left; cmp ptr1 bne @L1 cpx ptr1+1 @L1: bcs @L2 lda ptr1 ldx ptr1+1 ; Jump to memcpy, which will cleanup the stack and return to the caller @L2: jmp _memcpy ; ---------------------------------------------------------------------------- ; vsprintf - formatted output into a buffer ; ; int __fastcall__ vsnprintf (char* buf, size_t size, const char* format, va_list ap); ; _vsnprintf: pha ; Save low byte of ap ; Setup the outdesc structure lda #0 sta outdesc sta outdesc+1 ; Clear ccount ; Get the size parameter and replace it by a pointer to outdesc. This is to ; build a stack frame for the call to _printf. ; If size is zero, there's nothing to do. ldy #2 lda (sp),y sta ptr1 lda #outdesc sta (sp),y ; Write size-1 to the outdesc structure ldx ptr1 ldy ptr1+1 dex bne L1 dey L1: stx outdesc+6 sty outdesc+7 ; Copy buf to the outdesc structure ldy #5 jsr ldaxysp sta outdesc+4 stx outdesc+5 ; Restore low byte of ap and call _printf pla jsr __printf ; Terminate the string lda outdesc+0 ldx outdesc+1 cpx outdesc+7 bne L2 cmp outdesc+6 L2: bcc L3 lda outdesc+6 ldx outdesc+7 clc L3: adc outdesc+4 sta ptr1 txa adc outdesc+5 sta ptr1+1 lda #0 tay sta (ptr1),y ; Return the number of bytes written and drop buf lda outdesc ; ccount ldx outdesc+1 jmp incsp2 ; Bail out if size is zero L9: lda #0 tax jmp incsp6 ; Drop parameters