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
18 #include <linux/types.h>
19 #include <linux/string.h>
20 #include <linux/ctype.h>
21 #include <linux/kernel.h>
23 #include <asm/div64.h>
26 * simple_strtoul - convert a string to an unsigned long
27 * @cp: The start of the string
28 * @endp: A pointer to the end of the parsed string will be placed here
29 * @base: The number base to use
31 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
33 unsigned long result = 0,value;
40 if ((*cp == 'x') && isxdigit(cp[1])) {
46 while (isxdigit(*cp) &&
47 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
48 result = result*base + value;
57 * simple_strtol - convert a string to a signed long
58 * @cp: The start of the string
59 * @endp: A pointer to the end of the parsed string will be placed here
60 * @base: The number base to use
62 long simple_strtol(const char *cp,char **endp,unsigned int base)
65 return -simple_strtoul(cp+1,endp,base);
66 return simple_strtoul(cp,endp,base);
70 * simple_strtoull - convert a string to an unsigned long long
71 * @cp: The start of the string
72 * @endp: A pointer to the end of the parsed string will be placed here
73 * @base: The number base to use
75 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
77 unsigned long long result = 0,value;
84 if ((*cp == 'x') && isxdigit(cp[1])) {
90 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
91 ? toupper(*cp) : *cp)-'A'+10) < base) {
92 result = result*base + value;
101 * simple_strtoll - convert a string to a signed long long
102 * @cp: The start of the string
103 * @endp: A pointer to the end of the parsed string will be placed here
104 * @base: The number base to use
106 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
109 return -simple_strtoull(cp+1,endp,base);
110 return simple_strtoull(cp,endp,base);
113 static int skip_atoi(const char **s)
118 i = i*10 + *((*s)++) - '0';
122 #define ZEROPAD 1 /* pad with zero */
123 #define SIGN 2 /* unsigned/signed long */
124 #define PLUS 4 /* show plus */
125 #define SPACE 8 /* space if plus */
126 #define LEFT 16 /* left justified */
127 #define SPECIAL 32 /* 0x */
128 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
130 static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
134 const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
135 const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
138 digits = (type & LARGE) ? large_digits : small_digits;
141 if (base < 2 || base > 36)
143 c = (type & ZEROPAD) ? '0' : ' ';
150 } else if (type & PLUS) {
153 } else if (type & SPACE) {
158 if (type & SPECIAL) {
167 else while (num != 0)
168 tmp[i++] = digits[do_div(num,base)];
172 if (!(type&(ZEROPAD+LEFT))) {
184 if (type & SPECIAL) {
189 } else if (base==16) {
198 if (!(type & LEFT)) {
205 while (i < precision--) {
224 * vsnprintf - Format a string and place it in a buffer
225 * @buf: The buffer to place the result into
226 * @size: The size of the buffer, including the trailing null space
227 * @fmt: The format string to use
228 * @args: Arguments for the format string
230 * Call this function if you are already dealing with a va_list.
231 * You probably want snprintf instead.
233 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
236 unsigned long long num;
241 int flags; /* flags to number() */
243 int field_width; /* width of output field */
244 int precision; /* min. # of digits for integers; max
245 number of chars for from string */
246 int qualifier; /* 'h', 'l', or 'L' for integer fields */
247 /* 'z' support added 23/7/1999 S.H. */
248 /* 'z' changed to 'Z' --davidm 1/25/99 */
251 end = buf + size - 1;
255 size = end - buf + 1;
258 for (; *fmt ; ++fmt) {
269 ++fmt; /* this also skips first '%' */
271 case '-': flags |= LEFT; goto repeat;
272 case '+': flags |= PLUS; goto repeat;
273 case ' ': flags |= SPACE; goto repeat;
274 case '#': flags |= SPECIAL; goto repeat;
275 case '0': flags |= ZEROPAD; goto repeat;
278 /* get field width */
281 field_width = skip_atoi(&fmt);
282 else if (*fmt == '*') {
284 /* it's the next argument */
285 field_width = va_arg(args, int);
286 if (field_width < 0) {
287 field_width = -field_width;
292 /* get the precision */
297 precision = skip_atoi(&fmt);
298 else if (*fmt == '*') {
300 /* it's the next argument */
301 precision = va_arg(args, int);
307 /* get the conversion qualifier */
309 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
312 if (qualifier == 'l' && *fmt == 'l') {
323 if (!(flags & LEFT)) {
324 while (--field_width > 0) {
330 c = (unsigned char) va_arg(args, int);
334 while (--field_width > 0) {
342 s = va_arg(args, char *);
346 len = strnlen(s, precision);
348 if (!(flags & LEFT)) {
349 while (len < field_width--) {
355 for (i = 0; i < len; ++i) {
360 while (len < field_width--) {
368 if (field_width == -1) {
369 field_width = 2*sizeof(void *);
372 str = number(str, end,
373 (unsigned long) va_arg(args, void *),
374 16, field_width, precision, flags);
380 * What does C99 say about the overflow case here? */
381 if (qualifier == 'l') {
382 long * ip = va_arg(args, long *);
384 } else if (qualifier == 'Z') {
385 size_t * ip = va_arg(args, size_t *);
388 int * ip = va_arg(args, int *);
399 /* integer number formats - set up the flags and "break" */
429 if (qualifier == 'L')
430 num = va_arg(args, long long);
431 else if (qualifier == 'l') {
432 num = va_arg(args, unsigned long);
434 num = (signed long) num;
435 } else if (qualifier == 'Z') {
436 num = va_arg(args, size_t);
437 } else if (qualifier == 'h') {
438 num = (unsigned short) va_arg(args, int);
440 num = (signed short) num;
442 num = va_arg(args, unsigned int);
444 num = (signed int) num;
446 str = number(str, end, num, base,
447 field_width, precision, flags);
452 /* don't write out a null byte if the buf size is zero */
454 /* the trailing null byte doesn't count towards the total
461 * snprintf - Format a string and place it in a buffer
462 * @buf: The buffer to place the result into
463 * @size: The size of the buffer, including the trailing null space
464 * @fmt: The format string to use
465 * @...: Arguments for the format string
467 int snprintf(char * buf, size_t size, const char *fmt, ...)
473 i=vsnprintf(buf,size,fmt,args);
479 * vsprintf - Format a string and place it in a buffer
480 * @buf: The buffer to place the result into
481 * @fmt: The format string to use
482 * @args: Arguments for the format string
484 * Call this function if you are already dealing with a va_list.
485 * You probably want sprintf instead.
487 int vsprintf(char *buf, const char *fmt, va_list args)
489 return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
494 * sprintf - Format a string and place it in a buffer
495 * @buf: The buffer to place the result into
496 * @fmt: The format string to use
497 * @...: Arguments for the format string
499 int sprintf(char * buf, const char *fmt, ...)
505 i=vsprintf(buf,fmt,args);
511 * vsscanf - Unformat a buffer into a list of arguments
513 * @fmt: format of buffer
516 int vsscanf(const char * buf, const char * fmt, va_list args)
518 const char *str = buf;
523 int field_width = -1;
526 while(*fmt && *str) {
527 /* skip any white space in format */
528 /* white space in format matchs any amount of
529 * white space, including none, in the input.
532 while (isspace(*fmt))
534 while (isspace(*str))
538 /* anything that is not a conversion must match exactly */
539 if (*fmt != '%' && *fmt) {
540 if (*fmt++ != *str++)
549 /* skip this conversion.
550 * advance both strings to next white space
553 while (!isspace(*fmt) && *fmt)
555 while (!isspace(*str) && *str)
560 /* get field width */
562 field_width = skip_atoi(&fmt);
564 /* get conversion qualifier */
566 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') {
579 char *s = (char *) va_arg(args,char*);
580 if (field_width == -1)
584 } while(field_width-- > 0 && *str);
590 char *s = (char *) va_arg(args, char *);
591 if(field_width == -1)
592 field_width = INT_MAX;
593 /* first, skip leading white space in buffer */
594 while (isspace(*str))
597 /* now copy until next white space */
598 while (*str && !isspace(*str) && field_width--) {
606 /* return number of characters read so far */
608 int *i = (int *)va_arg(args,int*);
625 /* looking for '%' in str */
630 /* invalid format; stop here */
634 /* have some sort of integer conversion.
635 * first, skip white space in buffer.
637 while (isspace(*str))
640 if (!*str || !isdigit(*str))
646 short *s = (short *) va_arg(args,short *);
647 *s = (short) simple_strtol(str,&next,base);
649 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
650 *s = (unsigned short) simple_strtoul(str, &next, base);
655 long *l = (long *) va_arg(args,long *);
656 *l = simple_strtol(str,&next,base);
658 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
659 *l = simple_strtoul(str,&next,base);
664 long long *l = (long long*) va_arg(args,long long *);
665 *l = simple_strtoll(str,&next,base);
667 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
668 *l = simple_strtoull(str,&next,base);
673 size_t *s = (size_t*) va_arg(args,size_t*);
674 *s = (size_t) simple_strtoul(str,&next,base);
679 int *i = (int *) va_arg(args, int*);
680 *i = (int) simple_strtol(str,&next,base);
682 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
683 *i = (unsigned int) simple_strtoul(str,&next,base);
697 * sscanf - Unformat a buffer into a list of arguments
699 * @fmt: formatting of buffer
700 * @...: resulting arguments
702 int sscanf(const char * buf, const char * fmt, ...)
708 i = vsscanf(buf,fmt,args);