]> git.sur5r.net Git - cc65/blob - libsrc/common/vsnprintf.s
Made Olivers devnum patch (r4588) work with the PET-II models. On these
[cc65] / libsrc / common / vsnprintf.s
1 ;
2 ; int vsnprintf (char* Buf, size_t size, const char* Format, va_list ap);
3 ;
4 ; Ullrich von Bassewitz, 2009-09-26
5 ;
6
7         .export         _vsnprintf, vsnprintf
8         .import         ldaxysp, popax, incsp2, incsp6
9         .import         _memcpy, __printf
10         .importzp       sp, ptr1
11
12         .macpack        generic
13
14 .data
15
16 ; ----------------------------------------------------------------------------
17 ;
18 ; Static data for the _vsnprintf routine
19 ;
20
21 outdesc:                        ; Static outdesc structure
22 ccount: .word   0               ; ccount
23 func:   .word   out             ; Output function pointer
24 bufptr: .word   0               ; ptr
25 bufsize:.word   0               ; Buffer size
26
27 .code
28
29 ; ----------------------------------------------------------------------------
30 ; vsprintf - formatted output into a buffer
31 ;
32 ; int __fastcall__ vsnprintf (char* buf, size_t size, const char* format, va_list ap);
33 ;
34
35 _vsnprintf:
36         pha                     ; Save ap
37         txa
38         pha
39
40 ; Setup the outdesc structure. This is also an additional entry point for
41 ; vsprintf with ap on stack
42
43 vsnprintf:
44         lda     #0
45         sta     ccount+0
46         sta     ccount+1        ; Clear ccount
47
48 ; Get the size parameter and replace it by a pointer to outdesc. This is to
49 ; build a stack frame for the call to _printf.
50 ; If size is zero, there's nothing to do.
51
52         ldy     #2
53         lda     (sp),y
54         sta     ptr1
55
56         lda     #<outdesc
57         sta     (sp),y
58
59         iny
60         lda     (sp),y
61         sta     ptr1+1
62
63         ora     ptr1
64         beq     L9
65
66         lda     #>outdesc
67         sta     (sp),y
68
69 ; Write size-1 to outdesc.uns
70
71         ldy     ptr1+1
72         ldx     ptr1
73         bne     L1
74         dey
75 L1:     dex
76         stx     bufsize+0
77         sty     bufsize+1
78
79 ; Copy buf to the outdesc.ptr
80
81         ldy     #5
82         jsr     ldaxysp
83         sta     bufptr+0
84         stx     bufptr+1
85
86 ; Restore ap and call _printf
87
88         pla
89         tax
90         pla
91         jsr     __printf
92
93 ; Terminate the string. The last char is either at bufptr+ccount or
94 ; bufptr+bufsize, whichever is smaller.
95
96         lda     ccount+0
97         ldx     ccount+1
98         cpx     bufsize+1
99         bne     L2
100         cmp     bufsize+0
101 L2:     bcc     L3
102         lda     bufsize+0
103         ldx     bufsize+1
104         clc
105 L3:     adc     bufptr+0
106         sta     ptr1
107         txa
108         adc     bufptr+1
109         sta     ptr1+1
110
111         lda     #0
112         tay
113         sta     (ptr1),y
114
115 ; Return the number of bytes written and drop buf
116
117         lda     ccount+0
118         ldx     ccount+1
119         jmp     incsp2
120
121 ; Bail out if size is zero.
122
123 L9:     pla
124         pla                     ; Discard ap
125         lda     #0
126         tax
127         jmp     incsp6          ; Drop parameters
128
129
130 ; ----------------------------------------------------------------------------
131 ; Callback routine used for the actual output.
132 ;
133 ; static void out (struct outdesc* d, const char* buf, unsigned count)
134 ; /* Routine used for writing */
135 ;
136 ; Since we know, we're called with a pointer to our static outdesc structure,
137 ; we don't need the pointer passed on the stack.
138
139 out:
140
141 ; Calculate the space left in the buffer. If no space is left, don't copy
142 ; any characters
143
144         lda     bufsize+0               ; Low byte of buffer size
145         sec
146         sbc     ccount+0                ; Low byte of bytes already written
147         sta     ptr1
148         lda     bufsize+1
149         sbc     ccount+1
150         sta     ptr1+1
151         bcs     @L0                     ; Branch if space left
152         lda     #$00
153         sta     ptr1
154         sta     ptr1+1                  ; No space left
155
156 ; Replace the pointer to d by a pointer to the write position in the buffer
157 ; for the call to memcpy that follows.
158
159 @L0:    lda     bufptr+0
160         clc
161         adc     ccount+0
162         ldy     #4
163         sta     (sp),y
164
165         lda     bufptr+1
166         adc     ccount+1
167         iny
168         sta     (sp),y
169
170 ; Get Count from stack
171
172         jsr     popax
173
174 ; outdesc.ccount += Count;
175
176         pha
177         clc
178         adc     ccount+0
179         sta     ccount+0
180         txa
181         adc     ccount+1
182         sta     ccount+1
183         pla
184
185 ; if (Count > Left) Count = Left;
186
187         cpx     ptr1+1
188         bne     @L1
189         cmp     ptr1
190 @L1:    bcc     @L2
191         lda     ptr1
192         ldx     ptr1+1
193
194 ; Jump to memcpy, which will cleanup the stack and return to the caller
195
196 @L2:    jmp     _memcpy
197
198
199