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 :-)
23 #include <ddk/ntddk.h>
30 #include <internal/debug.h>
33 #define ZEROPAD 1 /* pad with zero */
34 #define SIGN 2 /* unsigned/signed long */
35 #define PLUS 4 /* show plus */
36 #define SPACE 8 /* space if plus */
37 #define LEFT 16 /* left justified */
38 #define SPECIAL 32 /* 0x */
39 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
42 #define do_div(n,base) ({ \
44 __res = ((unsigned long long) n) % (unsigned) base; \
45 n = ((unsigned long long) n) / (unsigned) base; \
49 static int skip_atoi(const char **s)
54 i = i*10 + *((*s)++) - '0';
60 number(char *buf, char *end, long long num, int base, int size, int precision, int type)
64 const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
65 const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
68 digits = (type & LARGE) ? large_digits : small_digits;
71 if (base < 2 || base > 36)
73 c = (type & ZEROPAD) ? '0' : ' ';
80 } else if (type & PLUS) {
83 } else if (type & SPACE) {
98 tmp[i++] = digits[do_div(num,base)];
102 if (!(type&(ZEROPAD+LEFT))) {
114 if (type & SPECIAL) {
119 } else if (base==16) {
128 if (!(type & LEFT)) {
135 while (i < precision--) {
154 string(char* buf, char* end, const char* s, int len, int field_width, int precision, int flags)
167 while (s[len] && (unsigned int)len < (unsigned int)precision)
172 if ((unsigned int)len > (unsigned int)precision)
177 while (len < field_width--)
183 for (i = 0; i < len; ++i)
189 while (len < field_width--)
199 stringw(char* buf, char* end, const wchar_t* sw, int len, int field_width, int precision, int flags)
204 sw = REACTOS_UCS2(L"<NULL>");
212 while (sw[len] && (unsigned int)len < (unsigned int)precision)
217 if ((unsigned int)len > (unsigned int)precision)
222 while (len < field_width--)
228 for (i = 0; i < len; ++i)
232 *buf = (unsigned char)(*sw++);
233 /* Although (wchar_t)[*sw] may be nonzero the resulting (unsigned char)
234 * becomes string terminator - we must terminate at that point
235 * to return the correct (unsigned char)-based string end pointer 'buf'.
242 while (len < field_width--)
251 int _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args)
254 unsigned long long num;
260 int flags; /* flags to number() */
262 int field_width; /* width of output field */
263 int precision; /* min. # of digits for integers; max
264 number of chars for from string */
265 int qualifier; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */
274 for ( ; *fmt ; ++fmt) {
285 ++fmt; /* this also skips first '%' */
287 case '-': flags |= LEFT; goto repeat;
288 case '+': flags |= PLUS; goto repeat;
289 case ' ': flags |= SPACE; goto repeat;
290 case '#': flags |= SPECIAL; goto repeat;
291 case '0': flags |= ZEROPAD; goto repeat;
294 /* get field width */
297 field_width = skip_atoi(&fmt);
298 else if (*fmt == '*') {
300 /* it's the next argument */
301 field_width = va_arg(args, int);
302 if (field_width < 0) {
303 field_width = -field_width;
308 /* get the precision */
313 precision = skip_atoi(&fmt);
314 else if (*fmt == '*') {
316 /* it's the next argument */
317 precision = va_arg(args, int);
323 /* get the conversion qualifier */
325 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') {
328 } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') {
337 case 'c': /* finished */
339 while (--field_width > 0)
345 if (qualifier == 'l' || qualifier == 'w')
348 *str = (unsigned char)(wchar_t) va_arg(args, int);
354 *str = (unsigned char) va_arg(args, int);
357 while (--field_width > 0)
365 case 'C': /* finished */
367 while (--field_width > 0)
373 if (qualifier == 'h')
376 *str = (unsigned char) va_arg(args, int);
382 *str = (unsigned char)(wchar_t) va_arg(args, int);
385 while (--field_width > 0)
393 case 's': /* finished */
394 if (qualifier == 'l' || qualifier == 'w') {
395 /* print unicode string */
396 sw = va_arg(args, wchar_t *);
397 str = stringw(str, end, sw, -1, field_width, precision, flags);
399 /* print ascii string */
400 s = va_arg(args, char *);
401 str = string(str, end, s, -1, field_width, precision, flags);
406 if (qualifier == 'h') {
407 /* print ascii string */
408 s = va_arg(args, char *);
409 str = string(str, end, s, -1, field_width, precision, flags);
411 /* print unicode string */
412 sw = va_arg(args, wchar_t *);
413 str = stringw(str, end, sw, -1, field_width, precision, flags);
418 if (qualifier == 'w') {
419 /* print counted unicode string */
420 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
421 if ((pus == NULL) || (pus->Buffer == NULL)) {
426 len = pus->Length / sizeof(WCHAR);
428 str = stringw(str, end, sw, len, field_width, precision, flags);
430 /* print counted ascii string */
431 PANSI_STRING pus = va_arg(args, PANSI_STRING);
432 if ((pus == NULL) || (pus->Buffer == NULL)) {
439 str = string(str, end, s, len, field_width, precision, flags);
444 if (field_width == -1) {
445 field_width = 2 * sizeof(void *);
448 str = number(str, end,
449 (unsigned long) va_arg(args, void *),
450 16, field_width, precision, flags);
454 /* FIXME: What does C99 say about the overflow case here? */
455 if (qualifier == 'l') {
456 long * ip = va_arg(args, long *);
459 int * ip = va_arg(args, int *);
464 /* integer number formats - set up the flags and "break" */
503 if (qualifier == 'I')
504 num = va_arg(args, unsigned long long);
505 else if (qualifier == 'l')
506 num = va_arg(args, unsigned long);
507 else if (qualifier == 'h') {
509 num = va_arg(args, int);
511 num = va_arg(args, unsigned int);
515 num = va_arg(args, int);
517 num = va_arg(args, unsigned int);
519 str = number(str, end, num, base, field_width, precision, flags);
525 /* don't write out a null byte if the buf size is zero */
532 int sprintf(char * buf, const char *fmt, ...)
538 i=_vsnprintf(buf,INT_MAX,fmt,args);
544 int _snprintf(char * buf, size_t cnt, const char *fmt, ...)
550 i=_vsnprintf(buf,cnt,fmt,args);
556 int vsprintf(char *buf, const char *fmt, va_list args)
558 return _vsnprintf(buf,INT_MAX,fmt,args);