]> git.sur5r.net Git - cc65/commitdiff
Added an (only roughly tested) implementation of vsnprintf
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 27 Sep 2009 12:04:36 +0000 (12:04 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 27 Sep 2009 12:04:36 +0000 (12:04 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4245 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/common/Makefile
libsrc/common/vsnprintf.s [new file with mode: 0644]

index a3e0b2cb013b80bc57efc8fef21c28b24c7fe2a8..0c6d768517494d2ad44f47309c4ce37bc60e7ac8 100644 (file)
@@ -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 (file)
index 0000000..2e5f8a0
--- /dev/null
@@ -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
+        iny
+        lda     (sp),y
+        sta     ptr1+1
+        ora     ptr1
+        beq     L9
+
+        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
+
+