3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/rtl/sprintf.c
6 * PURPOSE: Single byte sprintf functions
7 * PROGRAMMERS: David Welch
13 * linux/lib/vsprintf.c
15 * Copyright (C) 1991, 1992 Linus Torvalds
18 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
20 * Wirzenius wrote this portably, Torvalds fucked it up :-)
24 #include <internal/ctype.h>
25 #include <internal/debug.h>
28 #define ZEROPAD 1 /* pad with zero */
29 #define SIGN 2 /* unsigned/signed long */
30 #define PLUS 4 /* show plus */
31 #define SPACE 8 /* space if plus */
32 #define LEFT 16 /* left justified */
33 #define SPECIAL 32 /* 0x */
34 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
39 #define do_div(n,base) ({ \
41 __res = ((unsigned long long) n) % (unsigned) base; \
42 n = ((unsigned long long) n) / (unsigned) base; \
46 /* n /= base, "returns" remainder */
47 __inline
int int_do_div(__int64
* n
, int base
)
49 int __res
= (int)(((unsigned __int64
)*n
) % (unsigned) base
);
50 *n
= (int)(((unsigned __int64
)*n
) / (unsigned) base
);
53 #define do_div(n,base) int_do_div(&n, base)
58 static int skip_atoi(const char **s
)
63 i
= i
*10 + *((*s
)++) - '0';
70 number(char *buf
, char *end
, long long num
, int base
, int size
, int precision
, int type
)
72 number(char *buf
, char *end
, __int64 num
, int base
, int size
, int precision
, int type
)
77 const char *small_digits
= "0123456789abcdefghijklmnopqrstuvwxyz";
78 const char *large_digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
81 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
84 if (base
< 2 || base
> 36)
86 c
= (type
& ZEROPAD
) ? '0' : ' ';
93 } else if (type
& PLUS
) {
96 } else if (type
& SPACE
) {
101 if (type
& SPECIAL
) {
110 else while (num
!= 0)
111 tmp
[i
++] = digits
[do_div(num
,base
)];
115 if (!(type
&(ZEROPAD
+LEFT
))) {
127 if (type
& SPECIAL
) {
132 } else if (base
==16) {
141 if (!(type
& LEFT
)) {
148 while (i
< precision
--) {
167 string(char* buf
, char* end
, const char* s
, int len
, int field_width
, int precision
, int flags
)
180 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
185 if ((unsigned int)len
> (unsigned int)precision
)
190 while (len
< field_width
--)
196 for (i
= 0; i
< len
; ++i
)
202 while (len
< field_width
--)
212 stringw(char* buf
, char* end
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
225 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
230 if ((unsigned int)len
> (unsigned int)precision
)
235 while (len
< field_width
--)
241 for (i
= 0; i
< len
; ++i
)
244 *buf
= (unsigned char)(*sw
++);
247 while (len
< field_width
--)
259 int _vsnprintf(char *buf
, size_t cnt
, const char *fmt
, va_list args
)
262 #if defined(__GNUC__)
263 unsigned long long num
;
265 unsigned __int64 num
;
272 int flags
; /* flags to number() */
274 int field_width
; /* width of output field */
275 int precision
; /* min. # of digits for integers; max
276 number of chars for from string */
277 int qualifier
; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */
286 for ( ; *fmt
; ++fmt
) {
297 ++fmt
; /* this also skips first '%' */
299 case '-': flags
|= LEFT
; goto repeat
;
300 case '+': flags
|= PLUS
; goto repeat
;
301 case ' ': flags
|= SPACE
; goto repeat
;
302 case '#': flags
|= SPECIAL
; goto repeat
;
303 case '0': flags
|= ZEROPAD
; goto repeat
;
306 /* get field width */
309 field_width
= skip_atoi(&fmt
);
310 else if (*fmt
== '*') {
312 /* it's the next argument */
313 field_width
= va_arg(args
, int);
314 if (field_width
< 0) {
315 field_width
= -field_width
;
320 /* get the precision */
325 precision
= skip_atoi(&fmt
);
326 else if (*fmt
== '*') {
328 /* it's the next argument */
329 precision
= va_arg(args
, int);
335 /* get the conversion qualifier */
337 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' || *fmt
== 'w') {
340 } else if (*fmt
== 'I' && *(fmt
+1) == '6' && *(fmt
+2) == '4') {
349 case 'c': /* finished */
351 while (--field_width
> 0)
357 if (qualifier
== 'l' || qualifier
== 'w')
360 *str
= (unsigned char)(wchar_t) va_arg(args
, int);
366 *str
= (unsigned char) va_arg(args
, int);
369 while (--field_width
> 0)
377 case 'C': /* finished */
379 while (--field_width
> 0)
385 if (qualifier
== 'h')
388 *str
= (unsigned char) va_arg(args
, int);
394 *str
= (unsigned char)(wchar_t) va_arg(args
, int);
397 while (--field_width
> 0)
405 case 's': /* finished */
406 if (qualifier
== 'l' || qualifier
== 'w') {
407 /* print unicode string */
408 sw
= va_arg(args
, wchar_t *);
409 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
411 /* print ascii string */
412 s
= va_arg(args
, char *);
413 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
418 if (qualifier
== 'h') {
419 /* print ascii string */
420 s
= va_arg(args
, char *);
421 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
423 /* print unicode string */
424 sw
= va_arg(args
, wchar_t *);
425 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
430 if (qualifier
== 'w') {
431 /* print counted unicode string */
432 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
433 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
438 len
= pus
->Length
/ sizeof(WCHAR
);
440 str
= stringw(str
, end
, sw
, len
, field_width
, precision
, flags
);
442 /* print counted ascii string */
443 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
444 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
451 str
= string(str
, end
, s
, len
, field_width
, precision
, flags
);
456 if (field_width
== -1) {
457 field_width
= 2 * sizeof(void *);
460 str
= number(str
, end
,
461 (unsigned long) va_arg(args
, void *),
462 16, field_width
, precision
, flags
);
466 /* FIXME: What does C99 say about the overflow case here? */
467 if (qualifier
== 'l') {
468 long * ip
= va_arg(args
, long *);
471 int * ip
= va_arg(args
, int *);
476 /* integer number formats - set up the flags and "break" */
515 if (qualifier
== 'I')
516 #if defined(__GNUC__)
517 num
= va_arg(args
, unsigned long long);
519 num
= va_arg(args
, unsigned __int64
);
521 else if (qualifier
== 'l') {
523 num
= va_arg(args
, long);
525 num
= va_arg(args
, unsigned long);
527 else if (qualifier
== 'h') {
529 num
= va_arg(args
, int);
531 num
= va_arg(args
, unsigned int);
535 num
= va_arg(args
, int);
537 num
= va_arg(args
, unsigned int);
539 str
= number(str
, end
, num
, base
, field_width
, precision
, flags
);
545 /* don't write out a null byte if the buf size is zero */
555 int sprintf(char * buf
, const char *fmt
, ...)
561 i
=_vsnprintf(buf
,INT_MAX
,fmt
,args
);
570 int _snprintf(char * buf
, size_t cnt
, const char *fmt
, ...)
576 i
=_vsnprintf(buf
,cnt
,fmt
,args
);
585 int vsprintf(char *buf
, const char *fmt
, va_list args
)
587 return _vsnprintf(buf
,INT_MAX
,fmt
,args
);