1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-19 21:32:19 +00:00
cc65/libsrc/common/vsnprintf.s
uz 0b43444c26 Added an (only roughly tested) implementation of vsnprintf
git-svn-id: svn://svn.cc65.org/cc65/trunk@4245 b7a2c559-68d2-44c3-8de9-860c34a00d81
2009-09-27 12:04:36 +00:00

187 lines
3.9 KiB
ArmAsm

;
; 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