4 * Copyright (C) 1991, 1992 Linus Torvalds
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
13 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
14 * - changed to provide snprintf and vsnprintf functions
15 * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
16 * - scnprintf and vscnprintf
22 #include <sys/types.h>
24 #include <asm/ctype.h>
26 #include <asm/div64.h>
29 * simple_strtoul - convert a string to an unsigned long
30 * @cp: The start of the string
31 * @endp: A pointer to the end of the parsed string will be placed here
32 * @base: The number base to use
34 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
36 unsigned long result = 0,value;
43 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
48 } else if (base == 16) {
49 if (cp[0] == '0' && toupper(cp[1]) == 'X')
52 while (isxdigit(*cp) &&
53 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
54 result = result*base + value;
64 * simple_strtol - convert a string to a signed long
65 * @cp: The start of the string
66 * @endp: A pointer to the end of the parsed string will be placed here
67 * @base: The number base to use
69 long simple_strtol(const char *cp,char **endp,unsigned int base)
72 return -simple_strtoul(cp+1,endp,base);
73 return simple_strtoul(cp,endp,base);
78 * simple_strtoull - convert a string to an unsigned long long
79 * @cp: The start of the string
80 * @endp: A pointer to the end of the parsed string will be placed here
81 * @base: The number base to use
83 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
85 unsigned long long result = 0,value;
92 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
97 } else if (base == 16) {
98 if (cp[0] == '0' && toupper(cp[1]) == 'X')
101 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
102 ? toupper(*cp) : *cp)-'A'+10) < base) {
103 result = result*base + value;
113 * simple_strtoll - convert a string to a signed long long
114 * @cp: The start of the string
115 * @endp: A pointer to the end of the parsed string will be placed here
116 * @base: The number base to use
118 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
121 return -simple_strtoull(cp+1,endp,base);
122 return simple_strtoull(cp,endp,base);
125 static int skip_atoi(const char **s)
130 i = i*10 + *((*s)++) - '0';
134 #define ZEROPAD 1 /* pad with zero */
135 #define SIGN 2 /* unsigned/signed long */
136 #define PLUS 4 /* show plus */
137 #define SPACE 8 /* space if plus */
138 #define LEFT 16 /* left justified */
139 #define SPECIAL 32 /* 0x */
140 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
142 static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
146 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
147 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
150 digits = (type & LARGE) ? large_digits : small_digits;
153 if (base < 2 || base > 36)
155 c = (type & ZEROPAD) ? '0' : ' ';
158 if ((signed long long) num < 0) {
160 num = - (signed long long) num;
162 } else if (type & PLUS) {
165 } else if (type & SPACE) {
170 if (type & SPECIAL) {
179 else while (num != 0)
180 tmp[i++] = digits[do_div(num,base)];
184 if (!(type&(ZEROPAD+LEFT))) {
196 if (type & SPECIAL) {
201 } else if (base==16) {
210 if (!(type & LEFT)) {
217 while (i < precision--) {
236 * vsnprintf - Format a string and place it in a buffer
237 * @buf: The buffer to place the result into
238 * @size: The size of the buffer, including the trailing null space
239 * @fmt: The format string to use
240 * @args: Arguments for the format string
242 * The return value is the number of characters which would
243 * be generated for the given input, excluding the trailing
244 * '\0', as per ISO C99. If you want to have the exact
245 * number of characters written into @buf as return value
246 * (not including the trailing '\0'), use vscnprintf. If the
247 * return is greater than or equal to @size, the resulting
248 * string is truncated.
250 * Call this function if you are already dealing with a va_list.
251 * You probably want snprintf instead.
253 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
256 unsigned long long num;
261 int flags; /* flags to number() */
263 int field_width; /* width of output field */
264 int precision; /* min. # of digits for integers; max
265 number of chars for from string */
266 int qualifier; /* 'h', 'l', or 'L' for integer fields */
267 /* 'z' support added 23/7/1999 S.H. */
268 /* 'z' changed to 'Z' --davidm 1/25/99 */
269 /* 't' added for ptrdiff_t */
271 /* Reject out-of-range values early */
272 if ((int) size < 0) {
277 end = buf + size - 1;
281 size = end - buf + 1;
284 for (; *fmt ; ++fmt) {
295 ++fmt; /* this also skips first '%' */
297 case '-': flags |= LEFT; goto repeat;
298 case '+': flags |= PLUS; goto repeat;
299 case ' ': flags |= SPACE; goto repeat;
300 case '#': flags |= SPECIAL; goto repeat;
301 case '0': flags |= ZEROPAD; goto repeat;
304 /* get field width */
307 field_width = skip_atoi(&fmt);
308 else if (*fmt == '*') {
310 /* it's the next argument */
311 field_width = va_arg(args, int);
312 if (field_width < 0) {
313 field_width = -field_width;
318 /* get the precision */
323 precision = skip_atoi(&fmt);
324 else if (*fmt == '*') {
326 /* it's the next argument */
327 precision = va_arg(args, int);
333 /* get the conversion qualifier */
335 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
336 *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
339 if (qualifier == 'l' && *fmt == 'l') {
350 if (!(flags & LEFT)) {
351 while (--field_width > 0) {
357 c = (unsigned char) va_arg(args, int);
361 while (--field_width > 0) {
369 s = va_arg(args, char *);
371 len = strnlen(s, precision);
373 if (!(flags & LEFT)) {
374 while (len < field_width--) {
380 for (i = 0; i < len; ++i) {
385 while (len < field_width--) {
393 if (field_width == -1) {
394 field_width = 2*sizeof(void *);
397 str = number(str, end,
398 (unsigned long) va_arg(args, void *),
399 16, field_width, precision, flags);
405 * What does C99 say about the overflow case here? */
406 if (qualifier == 'l') {
407 long * ip = va_arg(args, long *);
409 } else if (qualifier == 'Z' || qualifier == 'z') {
410 size_t * ip = va_arg(args, size_t *);
413 int * ip = va_arg(args, int *);
424 /* integer number formats - set up the flags and "break" */
454 if (qualifier == 'L')
455 num = va_arg(args, long long);
456 else if (qualifier == 'l') {
457 num = va_arg(args, unsigned long);
459 num = (signed long) num;
460 } else if (qualifier == 'Z' || qualifier == 'z') {
461 num = va_arg(args, size_t);
462 } else if (qualifier == 't') {
463 num = va_arg(args, long);
464 } else if (qualifier == 'h') {
465 num = (unsigned short) va_arg(args, int);
467 num = (signed short) num;
469 num = va_arg(args, unsigned int);
471 num = (signed int) num;
473 str = number(str, end, num, base,
474 field_width, precision, flags);
479 /* don't write out a null byte if the buf size is zero */
481 /* the trailing null byte doesn't count towards the total
489 * vscnprintf - Format a string and place it in a buffer
490 * @buf: The buffer to place the result into
491 * @size: The size of the buffer, including the trailing null space
492 * @fmt: The format string to use
493 * @args: Arguments for the format string
495 * The return value is the number of characters which have been written into
496 * the @buf not including the trailing '\0'. If @size is <= 0 the function
499 * Call this function if you are already dealing with a va_list.
500 * You probably want scnprintf instead.
502 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
506 i=vsnprintf(buf,size,fmt,args);
507 return (i >= size) ? (size - 1) : i;
512 * snprintf - Format a string and place it in a buffer
513 * @buf: The buffer to place the result into
514 * @size: The size of the buffer, including the trailing null space
515 * @fmt: The format string to use
516 * @...: Arguments for the format string
518 * The return value is the number of characters which would be
519 * generated for the given input, excluding the trailing null,
520 * as per ISO C99. If the return is greater than or equal to
521 * @size, the resulting string is truncated.
523 int snprintf(char * buf, size_t size, const char *fmt, ...)
529 i=vsnprintf(buf,size,fmt,args);
536 * scnprintf - Format a string and place it in a buffer
537 * @buf: The buffer to place the result into
538 * @size: The size of the buffer, including the trailing null space
539 * @fmt: The format string to use
540 * @...: Arguments for the format string
542 * The return value is the number of characters written into @buf not including
543 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
544 * greater than or equal to @size, the resulting string is truncated.
547 int scnprintf(char * buf, size_t size, const char *fmt, ...)
553 i = vsnprintf(buf, size, fmt, args);
555 return (i >= size) ? (size - 1) : i;
559 * vsprintf - Format a string and place it in a buffer
560 * @buf: The buffer to place the result into
561 * @fmt: The format string to use
562 * @args: Arguments for the format string
564 * The function returns the number of characters written
565 * into @buf. Use vsnprintf or vscnprintf in order to avoid
568 * Call this function if you are already dealing with a va_list.
569 * You probably want sprintf instead.
571 int vsprintf(char *buf, const char *fmt, va_list args)
573 return vsnprintf(buf, INT_MAX, fmt, args);
578 * sprintf - Format a string and place it in a buffer
579 * @buf: The buffer to place the result into
580 * @fmt: The format string to use
581 * @...: Arguments for the format string
583 * The function returns the number of characters written
584 * into @buf. Use snprintf or scnprintf in order to avoid
587 int sprintf(char * buf, const char *fmt, ...)
593 i=vsnprintf(buf, INT_MAX, fmt, args);
600 * vsscanf - Unformat a buffer into a list of arguments
602 * @fmt: format of buffer
605 int vsscanf(const char * buf, const char * fmt, va_list args)
607 const char *str = buf;
616 while(*fmt && *str) {
617 /* skip any white space in format */
618 /* white space in format matchs any amount of
619 * white space, including none, in the input.
622 while (isspace(*fmt))
624 while (isspace(*str))
628 /* anything that is not a conversion must match exactly */
629 if (*fmt != '%' && *fmt) {
630 if (*fmt++ != *str++)
639 /* skip this conversion.
640 * advance both strings to next white space
643 while (!isspace(*fmt) && *fmt)
645 while (!isspace(*str) && *str)
650 /* get field width */
653 field_width = skip_atoi(&fmt);
655 /* get conversion qualifier */
657 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
658 *fmt == 'Z' || *fmt == 'z') {
660 if (qualifier == *fmt) {
661 if (qualifier == 'h') {
664 } else if (qualifier == 'l') {
679 char *s = (char *) va_arg(args,char*);
680 if (field_width == -1)
684 } while (--field_width > 0 && *str);
690 char *s = (char *) va_arg(args, char *);
691 if(field_width == -1)
692 field_width = INT_MAX;
693 /* first, skip leading white space in buffer */
694 while (isspace(*str))
697 /* now copy until next white space */
698 while (*str && !isspace(*str) && field_width--) {
706 /* return number of characters read so far */
708 int *i = (int *)va_arg(args,int*);
726 /* looking for '%' in str */
731 /* invalid format; stop here */
735 /* have some sort of integer conversion.
736 * first, skip white space in buffer.
738 while (isspace(*str))
742 if (is_sign && digit == '-')
746 || (base == 16 && !isxdigit(digit))
747 || (base == 10 && !isdigit(digit))
748 || (base == 8 && (!isdigit(digit) || digit > '7'))
749 || (base == 0 && !isdigit(digit)))
753 case 'H': /* that's 'hh' in format */
755 signed char *s = (signed char *) va_arg(args,signed char *);
756 *s = (signed char) simple_strtol(str,&next,base);
758 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
759 *s = (unsigned char) simple_strtoul(str, &next, base);
764 short *s = (short *) va_arg(args,short *);
765 *s = (short) simple_strtol(str,&next,base);
767 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
768 *s = (unsigned short) simple_strtoul(str, &next, base);
773 long *l = (long *) va_arg(args,long *);
774 *l = simple_strtol(str,&next,base);
776 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
777 *l = simple_strtoul(str,&next,base);
782 long long *l = (long long*) va_arg(args,long long *);
783 *l = simple_strtoll(str,&next,base);
785 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
786 *l = simple_strtoull(str,&next,base);
792 size_t *s = (size_t*) va_arg(args,size_t*);
793 *s = (size_t) simple_strtoul(str,&next,base);
798 int *i = (int *) va_arg(args, int*);
799 *i = (int) simple_strtol(str,&next,base);
801 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
802 *i = (unsigned int) simple_strtoul(str,&next,base);
817 * sscanf - Unformat a buffer into a list of arguments
819 * @fmt: formatting of buffer
820 * @...: resulting arguments
822 int sscanf(const char * buf, const char * fmt, ...)
828 i = vsscanf(buf,fmt,args);
833 /* generic puts() implementation independent of who provides putchar() */
834 int puts(const char *s)
836 #ifdef ARCH_HAS_CONSOLE