1bd185b41SIngo Weinhold /*
23ce26345SIngo Weinhold * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3bd185b41SIngo Weinhold * Copyright 2003-2008, Axel Dörfler. All rights reserved.
4bd185b41SIngo Weinhold * Distributed under the terms of the MIT license.
5bd185b41SIngo Weinhold *
6bd185b41SIngo Weinhold * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7bd185b41SIngo Weinhold * Distributed under the terms of the NewOS License.
8bd185b41SIngo Weinhold */
9bd185b41SIngo Weinhold
10bd185b41SIngo Weinhold
11bd185b41SIngo Weinhold #include <SupportDefs.h>
12bd185b41SIngo Weinhold
13bd185b41SIngo Weinhold #include <ctype.h>
143ce26345SIngo Weinhold #include <stdarg.h>
15bd185b41SIngo Weinhold #include <stdio.h>
163ce26345SIngo Weinhold #include <string.h>
173ce26345SIngo Weinhold
183ce26345SIngo Weinhold #include <algorithm>
19bd185b41SIngo Weinhold
20bd185b41SIngo Weinhold
21bd185b41SIngo Weinhold #define ZEROPAD 1 /* pad with zero */
22bd185b41SIngo Weinhold #define SIGN 2 /* unsigned/signed long */
23bd185b41SIngo Weinhold #define PLUS 4 /* show plus */
24bd185b41SIngo Weinhold #define SPACE 8 /* space if plus */
25bd185b41SIngo Weinhold #define LEFT 16 /* left justified */
26bd185b41SIngo Weinhold #define SPECIAL 32 /* 0x */
27bd185b41SIngo Weinhold #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
28bd185b41SIngo Weinhold
29bd185b41SIngo Weinhold #define FLOATING_SUPPORT
30bd185b41SIngo Weinhold
31bd185b41SIngo Weinhold
323ce26345SIngo Weinhold struct Buffer {
BufferBuffer333ce26345SIngo Weinhold Buffer(char* buffer, size_t size)
343ce26345SIngo Weinhold :
353ce26345SIngo Weinhold fCurrent(buffer),
363ce26345SIngo Weinhold fSize(size),
373ce26345SIngo Weinhold fBytesWritten(0)
383ce26345SIngo Weinhold {
393ce26345SIngo Weinhold }
403ce26345SIngo Weinhold
BytesWrittenBuffer413ce26345SIngo Weinhold size_t BytesWritten() const
423ce26345SIngo Weinhold {
433ce26345SIngo Weinhold return fBytesWritten;
443ce26345SIngo Weinhold }
453ce26345SIngo Weinhold
PutCharacterBuffer463ce26345SIngo Weinhold void PutCharacter(char c)
473ce26345SIngo Weinhold {
483ce26345SIngo Weinhold if (fBytesWritten < fSize) {
493ce26345SIngo Weinhold *fCurrent = c;
503ce26345SIngo Weinhold fCurrent++;
513ce26345SIngo Weinhold }
523ce26345SIngo Weinhold
533ce26345SIngo Weinhold fBytesWritten++;
543ce26345SIngo Weinhold }
553ce26345SIngo Weinhold
PutPaddingBuffer563ce26345SIngo Weinhold void PutPadding(int32 count)
573ce26345SIngo Weinhold {
583ce26345SIngo Weinhold if (count <= 0)
593ce26345SIngo Weinhold return;
603ce26345SIngo Weinhold
613ce26345SIngo Weinhold if (fBytesWritten < fSize) {
623ce26345SIngo Weinhold int32 toWrite = std::min(fSize - fBytesWritten, (size_t)count);
633ce26345SIngo Weinhold while (--toWrite >= 0)
643ce26345SIngo Weinhold *fCurrent++ = ' ';
653ce26345SIngo Weinhold }
663ce26345SIngo Weinhold
673ce26345SIngo Weinhold fBytesWritten += count;
683ce26345SIngo Weinhold }
693ce26345SIngo Weinhold
PutStringBuffer703ce26345SIngo Weinhold void PutString(const char *source, int32 length)
713ce26345SIngo Weinhold {
723ce26345SIngo Weinhold if (length <= 0)
733ce26345SIngo Weinhold return;
743ce26345SIngo Weinhold
753ce26345SIngo Weinhold if (fBytesWritten < fSize) {
763ce26345SIngo Weinhold int32 toWrite = std::min(fSize - fBytesWritten, (size_t)length);
773ce26345SIngo Weinhold memcpy(fCurrent, source, toWrite);
783ce26345SIngo Weinhold fCurrent += toWrite;
793ce26345SIngo Weinhold }
803ce26345SIngo Weinhold
813ce26345SIngo Weinhold fBytesWritten += length;
823ce26345SIngo Weinhold }
833ce26345SIngo Weinhold
NullTerminateBuffer843ce26345SIngo Weinhold void NullTerminate()
853ce26345SIngo Weinhold {
863ce26345SIngo Weinhold if (fBytesWritten < fSize)
873ce26345SIngo Weinhold *fCurrent = '\0';
883ce26345SIngo Weinhold else if (fSize > 0)
893ce26345SIngo Weinhold fCurrent[-1] = '\0';
903ce26345SIngo Weinhold }
913ce26345SIngo Weinhold
923ce26345SIngo Weinhold private:
933ce26345SIngo Weinhold char* fCurrent;
943ce26345SIngo Weinhold size_t fSize;
953ce26345SIngo Weinhold size_t fBytesWritten;
963ce26345SIngo Weinhold };
973ce26345SIngo Weinhold
983ce26345SIngo Weinhold
99bd185b41SIngo Weinhold static int
skip_atoi(const char ** s)100bd185b41SIngo Weinhold skip_atoi(const char **s)
101bd185b41SIngo Weinhold {
102bd185b41SIngo Weinhold int i = 0;
103bd185b41SIngo Weinhold
104bd185b41SIngo Weinhold while (isdigit(**s))
105bd185b41SIngo Weinhold i = i*10 + *((*s)++) - '0';
106bd185b41SIngo Weinhold
107bd185b41SIngo Weinhold return i;
108bd185b41SIngo Weinhold }
109bd185b41SIngo Weinhold
110bd185b41SIngo Weinhold
111bd185b41SIngo Weinhold static uint64
do_div(uint64 * _number,uint32 base)112bd185b41SIngo Weinhold do_div(uint64 *_number, uint32 base)
113bd185b41SIngo Weinhold {
114bd185b41SIngo Weinhold uint64 result = *_number % (uint64)base;
115bd185b41SIngo Weinhold *_number = *_number / (uint64)base;
116bd185b41SIngo Weinhold
117bd185b41SIngo Weinhold return result;
118bd185b41SIngo Weinhold }
119bd185b41SIngo Weinhold
120bd185b41SIngo Weinhold
121bd185b41SIngo Weinhold static char
sign_symbol(int flags,bool negative)122bd185b41SIngo Weinhold sign_symbol(int flags, bool negative)
123bd185b41SIngo Weinhold {
124bd185b41SIngo Weinhold if ((flags & SIGN) == 0)
125bd185b41SIngo Weinhold return '\0';
126bd185b41SIngo Weinhold
127bd185b41SIngo Weinhold if (negative)
128bd185b41SIngo Weinhold return '-';
129bd185b41SIngo Weinhold else if ((flags & PLUS) != 0)
130bd185b41SIngo Weinhold return '+';
131bd185b41SIngo Weinhold else if ((flags & SPACE) != 0)
132bd185b41SIngo Weinhold return ' ';
133bd185b41SIngo Weinhold
134bd185b41SIngo Weinhold return '\0';
135bd185b41SIngo Weinhold }
136bd185b41SIngo Weinhold
137bd185b41SIngo Weinhold
138bd185b41SIngo Weinhold static void
number(Buffer & outBuffer,uint64 num,uint32 base,int size,int precision,int flags)1393ce26345SIngo Weinhold number(Buffer& outBuffer, uint64 num, uint32 base, int size,
140bd185b41SIngo Weinhold int precision, int flags)
141bd185b41SIngo Weinhold {
142bd185b41SIngo Weinhold const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
143bd185b41SIngo Weinhold char c, sign, tmp[66];
144bd185b41SIngo Weinhold int i;
145bd185b41SIngo Weinhold
146bd185b41SIngo Weinhold if (flags & LARGE)
147bd185b41SIngo Weinhold digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
148bd185b41SIngo Weinhold if (flags & LEFT)
149bd185b41SIngo Weinhold flags &= ~ZEROPAD;
150bd185b41SIngo Weinhold if (base < 2 || base > 36)
151bd185b41SIngo Weinhold return;
152bd185b41SIngo Weinhold
153bd185b41SIngo Weinhold c = (flags & ZEROPAD) ? '0' : ' ';
154bd185b41SIngo Weinhold
155bd185b41SIngo Weinhold if (flags & SIGN) {
156bd185b41SIngo Weinhold sign = sign_symbol(flags, (int64)num < 0);
157bd185b41SIngo Weinhold if ((int64)num < 0)
158bd185b41SIngo Weinhold num = -(int64)num;
159bd185b41SIngo Weinhold if (sign)
160bd185b41SIngo Weinhold size--;
161bd185b41SIngo Weinhold } else
162bd185b41SIngo Weinhold sign = 0;
163bd185b41SIngo Weinhold
164bd185b41SIngo Weinhold if ((flags & SPECIAL) != 0) {
165bd185b41SIngo Weinhold if (base == 16)
166bd185b41SIngo Weinhold size -= 2;
167bd185b41SIngo Weinhold else if (base == 8)
168bd185b41SIngo Weinhold size--;
169bd185b41SIngo Weinhold }
170bd185b41SIngo Weinhold
171bd185b41SIngo Weinhold i = 0;
172bd185b41SIngo Weinhold if (num == 0)
173bd185b41SIngo Weinhold tmp[i++] = '0';
174bd185b41SIngo Weinhold else while (num != 0)
175bd185b41SIngo Weinhold tmp[i++] = digits[do_div(&num, base)];
176bd185b41SIngo Weinhold
177bd185b41SIngo Weinhold if (i > precision)
178bd185b41SIngo Weinhold precision = i;
179bd185b41SIngo Weinhold size -= precision;
180bd185b41SIngo Weinhold
181bd185b41SIngo Weinhold if (!(flags & (ZEROPAD + LEFT))) {
1823ce26345SIngo Weinhold outBuffer.PutPadding(size);
183bd185b41SIngo Weinhold size = 0;
184bd185b41SIngo Weinhold }
185bd185b41SIngo Weinhold if (sign)
1863ce26345SIngo Weinhold outBuffer.PutCharacter(sign);
187bd185b41SIngo Weinhold
188bd185b41SIngo Weinhold if ((flags & SPECIAL) != 0) {
189bd185b41SIngo Weinhold if (base == 8)
1903ce26345SIngo Weinhold outBuffer.PutCharacter('0');
191bd185b41SIngo Weinhold else if (base == 16) {
1923ce26345SIngo Weinhold outBuffer.PutCharacter('0');
1933ce26345SIngo Weinhold outBuffer.PutCharacter(digits[33]);
194bd185b41SIngo Weinhold }
195bd185b41SIngo Weinhold }
196bd185b41SIngo Weinhold
197bd185b41SIngo Weinhold if (!(flags & LEFT)) {
198bd185b41SIngo Weinhold while (size-- > 0)
1993ce26345SIngo Weinhold outBuffer.PutCharacter(c);
200bd185b41SIngo Weinhold }
201bd185b41SIngo Weinhold while (i < precision--)
2023ce26345SIngo Weinhold outBuffer.PutCharacter('0');
203bd185b41SIngo Weinhold while (i-- > 0)
2043ce26345SIngo Weinhold outBuffer.PutCharacter(tmp[i]);
205bd185b41SIngo Weinhold
2063ce26345SIngo Weinhold outBuffer.PutPadding(size);
207bd185b41SIngo Weinhold }
208bd185b41SIngo Weinhold
209bd185b41SIngo Weinhold
210bd185b41SIngo Weinhold #ifdef FLOATING_SUPPORT
211bd185b41SIngo Weinhold /*!
212bd185b41SIngo Weinhold This is a very basic floating point to string conversion routine.
213bd185b41SIngo Weinhold It prints up to 3 fraction digits, and doesn't support any precision arguments.
214bd185b41SIngo Weinhold It's just here for your convenience so that you can use it for debug output.
215bd185b41SIngo Weinhold */
2163ce26345SIngo Weinhold static void
floating(Buffer & outBuffer,double value,int fieldWidth,int flags)2173ce26345SIngo Weinhold floating(Buffer& outBuffer, double value, int fieldWidth, int flags)
218bd185b41SIngo Weinhold {
219bd185b41SIngo Weinhold char buffer[66];
220bd185b41SIngo Weinhold uint64 fraction;
221bd185b41SIngo Weinhold uint64 integer;
222bd185b41SIngo Weinhold int32 length = 0;
223bd185b41SIngo Weinhold char sign;
224bd185b41SIngo Weinhold
225bd185b41SIngo Weinhold sign = sign_symbol(flags, value < 0.0);
226bd185b41SIngo Weinhold if (value < 0.0)
227bd185b41SIngo Weinhold value = -value;
228bd185b41SIngo Weinhold
229bd185b41SIngo Weinhold fraction = (uint64)(value * 1000) % 1000;
230bd185b41SIngo Weinhold integer = (uint64)value;
231bd185b41SIngo Weinhold
232bd185b41SIngo Weinhold // put fraction part, if any
233bd185b41SIngo Weinhold
234bd185b41SIngo Weinhold if (fraction != 0) {
235bd185b41SIngo Weinhold bool first = true;
236bd185b41SIngo Weinhold while (fraction != 0) {
237bd185b41SIngo Weinhold int digit = do_div(&fraction, 10);
238bd185b41SIngo Weinhold if (!first || digit > 0) {
239bd185b41SIngo Weinhold buffer[length++] = '0' + digit;
240bd185b41SIngo Weinhold first = false;
241bd185b41SIngo Weinhold }
242bd185b41SIngo Weinhold }
243bd185b41SIngo Weinhold
244bd185b41SIngo Weinhold buffer[length++] = '.';
245bd185b41SIngo Weinhold }
246bd185b41SIngo Weinhold
247bd185b41SIngo Weinhold // put integer part
248bd185b41SIngo Weinhold
2493ce26345SIngo Weinhold if (integer == 0) {
250bd185b41SIngo Weinhold buffer[length++] = '0';
2513ce26345SIngo Weinhold } else {
2523ce26345SIngo Weinhold while (integer != 0)
253bd185b41SIngo Weinhold buffer[length++] = '0' + do_div(&integer, 10);
254bd185b41SIngo Weinhold }
255bd185b41SIngo Weinhold
256bd185b41SIngo Weinhold // write back to string
257bd185b41SIngo Weinhold
2583ce26345SIngo Weinhold if (!(flags & LEFT))
2593ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth);
260bd185b41SIngo Weinhold
2613ce26345SIngo Weinhold if (sign)
2623ce26345SIngo Weinhold outBuffer.PutCharacter(sign);
263bd185b41SIngo Weinhold
2643ce26345SIngo Weinhold while (length-- > 0)
2653ce26345SIngo Weinhold outBuffer.PutCharacter(buffer[length]);
266bd185b41SIngo Weinhold
2673ce26345SIngo Weinhold if ((flags & LEFT) != 0)
2683ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth);
269bd185b41SIngo Weinhold }
270bd185b41SIngo Weinhold #endif // FLOATING_SUPPORT
271bd185b41SIngo Weinhold
272bd185b41SIngo Weinhold
273bd185b41SIngo Weinhold int
vsnprintf(char * buffer,size_t bufferSize,const char * format,va_list args)274bd185b41SIngo Weinhold vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
275bd185b41SIngo Weinhold {
276bd185b41SIngo Weinhold uint64 num;
277bd185b41SIngo Weinhold int base;
278bd185b41SIngo Weinhold int flags; /* flags to number() */
279bd185b41SIngo Weinhold int fieldWidth; /* width of output field */
280bd185b41SIngo Weinhold int precision;
281bd185b41SIngo Weinhold /* min. # of digits for integers; max number of chars for from string */
282bd185b41SIngo Weinhold int qualifier; /* 'h', 'l', or 'L' for integer fields */
283bd185b41SIngo Weinhold
2843ce26345SIngo Weinhold Buffer outBuffer(buffer, bufferSize);
285bd185b41SIngo Weinhold
2863ce26345SIngo Weinhold for (; format[0]; format++) {
287bd185b41SIngo Weinhold if (format[0] != '%') {
2883ce26345SIngo Weinhold outBuffer.PutCharacter(format[0]);
289bd185b41SIngo Weinhold continue;
290bd185b41SIngo Weinhold }
291bd185b41SIngo Weinhold
292bd185b41SIngo Weinhold /* process flags */
293bd185b41SIngo Weinhold
294bd185b41SIngo Weinhold flags = 0;
295bd185b41SIngo Weinhold
296bd185b41SIngo Weinhold repeat:
297bd185b41SIngo Weinhold format++;
298bd185b41SIngo Weinhold /* this also skips first '%' */
299bd185b41SIngo Weinhold switch (format[0]) {
300bd185b41SIngo Weinhold case '-': flags |= LEFT; goto repeat;
301bd185b41SIngo Weinhold case '+': flags |= PLUS; goto repeat;
302bd185b41SIngo Weinhold case ' ': flags |= SPACE; goto repeat;
303bd185b41SIngo Weinhold case '#': flags |= SPECIAL; goto repeat;
304bd185b41SIngo Weinhold case '0': flags |= ZEROPAD; goto repeat;
305bd185b41SIngo Weinhold
306bd185b41SIngo Weinhold case '%':
3073ce26345SIngo Weinhold outBuffer.PutCharacter(format[0]);
308bd185b41SIngo Weinhold continue;
309bd185b41SIngo Weinhold }
310bd185b41SIngo Weinhold
311bd185b41SIngo Weinhold /* get field width */
312bd185b41SIngo Weinhold
313bd185b41SIngo Weinhold fieldWidth = -1;
314bd185b41SIngo Weinhold if (isdigit(*format))
315bd185b41SIngo Weinhold fieldWidth = skip_atoi(&format);
316bd185b41SIngo Weinhold else if (format[0] == '*') {
317bd185b41SIngo Weinhold format++;
318bd185b41SIngo Weinhold /* it's the next argument */
319bd185b41SIngo Weinhold fieldWidth = va_arg(args, int);
320bd185b41SIngo Weinhold if (fieldWidth < 0) {
321bd185b41SIngo Weinhold fieldWidth = -fieldWidth;
322bd185b41SIngo Weinhold flags |= LEFT;
323bd185b41SIngo Weinhold }
324bd185b41SIngo Weinhold }
325bd185b41SIngo Weinhold
326bd185b41SIngo Weinhold /* get the precision */
327bd185b41SIngo Weinhold
328bd185b41SIngo Weinhold precision = -1;
329bd185b41SIngo Weinhold if (format[0] == '.') {
330bd185b41SIngo Weinhold format++;
331bd185b41SIngo Weinhold if (isdigit(*format))
332bd185b41SIngo Weinhold precision = skip_atoi(&format);
333bd185b41SIngo Weinhold else if (format[0] == '*') {
334bd185b41SIngo Weinhold format++;
335bd185b41SIngo Weinhold /* it's the next argument */
336bd185b41SIngo Weinhold precision = va_arg(args, int);
337bd185b41SIngo Weinhold }
338bd185b41SIngo Weinhold if (precision < 0)
339bd185b41SIngo Weinhold precision = 0;
340bd185b41SIngo Weinhold }
341bd185b41SIngo Weinhold
342bd185b41SIngo Weinhold /* get the conversion qualifier */
343bd185b41SIngo Weinhold
344bd185b41SIngo Weinhold qualifier = -1;
3452ebcf777SAxel Dörfler if (format[0] == 'h' || format[0] == 'L' || format[0] == 'z') {
346bd185b41SIngo Weinhold qualifier = *format++;
347bd185b41SIngo Weinhold } else if (format[0] == 'l') {
348bd185b41SIngo Weinhold format++;
349bd185b41SIngo Weinhold if (format[0] == 'l') {
350bd185b41SIngo Weinhold qualifier = 'L';
351bd185b41SIngo Weinhold format++;
352bd185b41SIngo Weinhold } else
353bd185b41SIngo Weinhold qualifier = 'l';
354bd185b41SIngo Weinhold }
355bd185b41SIngo Weinhold
356bd185b41SIngo Weinhold /* default base */
357bd185b41SIngo Weinhold base = 10;
358bd185b41SIngo Weinhold
359bd185b41SIngo Weinhold switch (format[0]) {
360bd185b41SIngo Weinhold case 'c':
3613ce26345SIngo Weinhold if (!(flags & LEFT))
3623ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth - 1);
363bd185b41SIngo Weinhold
3643ce26345SIngo Weinhold outBuffer.PutCharacter((char)va_arg(args, int));
365bd185b41SIngo Weinhold
3663ce26345SIngo Weinhold if ((flags & LEFT) != 0)
3673ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth - 1);
368bd185b41SIngo Weinhold continue;
369bd185b41SIngo Weinhold
370bd185b41SIngo Weinhold case 's':
371bd185b41SIngo Weinhold {
372bd185b41SIngo Weinhold const char *argument = va_arg(args, char *);
373bd185b41SIngo Weinhold int32 length;
374bd185b41SIngo Weinhold
375bd185b41SIngo Weinhold if (argument == NULL)
376bd185b41SIngo Weinhold argument = "<NULL>";
377bd185b41SIngo Weinhold
378bd185b41SIngo Weinhold length = strnlen(argument, precision);
379bd185b41SIngo Weinhold fieldWidth -= length;
380bd185b41SIngo Weinhold
3813ce26345SIngo Weinhold if (!(flags & LEFT))
3823ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth);
383bd185b41SIngo Weinhold
3843ce26345SIngo Weinhold outBuffer.PutString(argument, length);
385bd185b41SIngo Weinhold
3863ce26345SIngo Weinhold if ((flags & LEFT) != 0)
3873ce26345SIngo Weinhold outBuffer.PutPadding(fieldWidth);
388bd185b41SIngo Weinhold continue;
389bd185b41SIngo Weinhold }
390bd185b41SIngo Weinhold
391bd185b41SIngo Weinhold #ifdef FLOATING_SUPPORT
392bd185b41SIngo Weinhold case 'f':
393bd185b41SIngo Weinhold case 'F':
394bd185b41SIngo Weinhold case 'g':
395bd185b41SIngo Weinhold case 'G':
396bd185b41SIngo Weinhold {
397bd185b41SIngo Weinhold double value = va_arg(args, double);
3983ce26345SIngo Weinhold floating(outBuffer, value, fieldWidth, flags | SIGN);
399bd185b41SIngo Weinhold continue;
400bd185b41SIngo Weinhold }
401bd185b41SIngo Weinhold #endif // FLOATING_SUPPORT
402bd185b41SIngo Weinhold
403bd185b41SIngo Weinhold case 'p':
404bd185b41SIngo Weinhold if (fieldWidth == -1) {
405bd185b41SIngo Weinhold fieldWidth = 2*sizeof(void *);
406bd185b41SIngo Weinhold flags |= ZEROPAD;
407bd185b41SIngo Weinhold }
408bd185b41SIngo Weinhold
4093ce26345SIngo Weinhold outBuffer.PutString("0x", 2);
4104be4fc6bSAlex Smith number(outBuffer, (addr_t)va_arg(args, void *), 16, fieldWidth,
4113ce26345SIngo Weinhold precision, flags);
412bd185b41SIngo Weinhold continue;
413bd185b41SIngo Weinhold
414bd185b41SIngo Weinhold case 'n':
415bd185b41SIngo Weinhold if (qualifier == 'l') {
416bd185b41SIngo Weinhold long *ip = va_arg(args, long *);
4173ce26345SIngo Weinhold *ip = outBuffer.BytesWritten();
418bd185b41SIngo Weinhold } else {
419bd185b41SIngo Weinhold int *ip = va_arg(args, int *);
4203ce26345SIngo Weinhold *ip = outBuffer.BytesWritten();
421bd185b41SIngo Weinhold }
422bd185b41SIngo Weinhold continue;
423bd185b41SIngo Weinhold
424bd185b41SIngo Weinhold /* integer number formats - set up the flags and "break" */
425bd185b41SIngo Weinhold case 'o':
426bd185b41SIngo Weinhold base = 8;
427bd185b41SIngo Weinhold break;
428bd185b41SIngo Weinhold
429bd185b41SIngo Weinhold case 'X':
430bd185b41SIngo Weinhold flags |= LARGE;
431bd185b41SIngo Weinhold case 'x':
432bd185b41SIngo Weinhold base = 16;
433bd185b41SIngo Weinhold break;
434bd185b41SIngo Weinhold
435bd185b41SIngo Weinhold case 'd':
436bd185b41SIngo Weinhold case 'i':
437bd185b41SIngo Weinhold flags |= SIGN;
438bd185b41SIngo Weinhold case 'u':
439bd185b41SIngo Weinhold break;
440bd185b41SIngo Weinhold
441bd185b41SIngo Weinhold default:
442bd185b41SIngo Weinhold if (format[0] != '%')
4433ce26345SIngo Weinhold outBuffer.PutCharacter('%');
444bd185b41SIngo Weinhold
445bd185b41SIngo Weinhold if (!format[0])
446bd185b41SIngo Weinhold goto out;
447bd185b41SIngo Weinhold
4483ce26345SIngo Weinhold outBuffer.PutCharacter(format[0]);
449bd185b41SIngo Weinhold continue;
450bd185b41SIngo Weinhold }
451bd185b41SIngo Weinhold
452bd185b41SIngo Weinhold if (qualifier == 'L')
453*014f4403SAlex Smith num = va_arg(args, unsigned long long);
454bd185b41SIngo Weinhold else if (qualifier == 'l') {
455*014f4403SAlex Smith num = va_arg(args, unsigned long);
4562ebcf777SAxel Dörfler if ((flags & SIGN) != 0)
457*014f4403SAlex Smith num = (long)num;
4582ebcf777SAxel Dörfler } else if (qualifier == 'z') {
4592ebcf777SAxel Dörfler num = va_arg(args, size_t);
4602ebcf777SAxel Dörfler if ((flags & SIGN) != 0)
461bd185b41SIngo Weinhold num = (long)num;
462bd185b41SIngo Weinhold } else if (qualifier == 'h') {
463bd185b41SIngo Weinhold num = (unsigned short)va_arg(args, int);
4642ebcf777SAxel Dörfler if ((flags & SIGN) != 0)
465bd185b41SIngo Weinhold num = (short)num;
4662ebcf777SAxel Dörfler } else if ((flags & SIGN) != 0)
467bd185b41SIngo Weinhold num = va_arg(args, int);
468bd185b41SIngo Weinhold else
469bd185b41SIngo Weinhold num = va_arg(args, unsigned int);
470bd185b41SIngo Weinhold
4713ce26345SIngo Weinhold number(outBuffer, num, base, fieldWidth, precision, flags);
472bd185b41SIngo Weinhold }
473bd185b41SIngo Weinhold
474bd185b41SIngo Weinhold out:
4753ce26345SIngo Weinhold outBuffer.NullTerminate();
4763ce26345SIngo Weinhold return outBuffer.BytesWritten();
477bd185b41SIngo Weinhold }
478bd185b41SIngo Weinhold
479bd185b41SIngo Weinhold
480bd185b41SIngo Weinhold int
vsprintf(char * buffer,const char * format,va_list args)481bd185b41SIngo Weinhold vsprintf(char *buffer, const char *format, va_list args)
482bd185b41SIngo Weinhold {
483bd185b41SIngo Weinhold return vsnprintf(buffer, ~0UL, format, args);
484bd185b41SIngo Weinhold }
485bd185b41SIngo Weinhold
486bd185b41SIngo Weinhold
487bd185b41SIngo Weinhold int
snprintf(char * buffer,size_t bufferSize,const char * format,...)488bd185b41SIngo Weinhold snprintf(char *buffer, size_t bufferSize, const char *format, ...)
489bd185b41SIngo Weinhold {
490bd185b41SIngo Weinhold va_list args;
491bd185b41SIngo Weinhold int i;
492bd185b41SIngo Weinhold
493bd185b41SIngo Weinhold va_start(args, format);
494bd185b41SIngo Weinhold i = vsnprintf(buffer, bufferSize, format, args);
495bd185b41SIngo Weinhold va_end(args);
496bd185b41SIngo Weinhold
497bd185b41SIngo Weinhold return i;
498bd185b41SIngo Weinhold }
499bd185b41SIngo Weinhold
500bd185b41SIngo Weinhold
501bd185b41SIngo Weinhold int
sprintf(char * buffer,const char * format,...)502bd185b41SIngo Weinhold sprintf(char *buffer, const char *format, ...)
503bd185b41SIngo Weinhold {
504bd185b41SIngo Weinhold va_list args;
505bd185b41SIngo Weinhold int i;
506bd185b41SIngo Weinhold
507bd185b41SIngo Weinhold va_start(args, format);
508bd185b41SIngo Weinhold i = vsnprintf(buffer, ~0UL, format, args);
509bd185b41SIngo Weinhold va_end(args);
510bd185b41SIngo Weinhold
511bd185b41SIngo Weinhold return i;
512bd185b41SIngo Weinhold }
513bd185b41SIngo Weinhold
514