From 0b43444c2663447d5a838451cb395b45d406ab8a Mon Sep 17 00:00:00 2001 From: uz Date: Sun, 27 Sep 2009 12:04:36 +0000 Subject: [PATCH] Added an (only roughly tested) implementation of vsnprintf git-svn-id: svn://svn.cc65.org/cc65/trunk@4245 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/common/Makefile | 1 + libsrc/common/vsnprintf.s | 186 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 libsrc/common/vsnprintf.s diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile index a3e0b2cb0..0c6d76851 100644 --- a/libsrc/common/Makefile +++ b/libsrc/common/Makefile @@ -192,6 +192,7 @@ S_OBJS = _cwd.o \ vfscanf.o \ vprintf.o \ vscanf.o \ + vsnprintf.o \ vsprintf.o \ vsscanf.o \ zerobss.o diff --git a/libsrc/common/vsnprintf.s b/libsrc/common/vsnprintf.s new file mode 100644 index 000000000..2e5f8a056 --- /dev/null +++ b/libsrc/common/vsnprintf.s @@ -0,0 +1,186 @@ +; +; 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 + + -- 2.39.2