4 * Copyright (C) 1991, 1992 Linus Torvalds
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
19 * simple_strtoul - convert a string to an unsigned long
20 * @cp: The start of the string
21 * @endp: A pointer to the end of the parsed string will be placed here
22 * @base: The number base to use
24 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
26 unsigned long result = 0,value;
33 if ((*cp == 'x') && isxdigit(cp[1])) {
39 while (isxdigit(*cp) &&
40 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
41 result = result*base + value;
50 * simple_strtol - convert a string to a signed long
51 * @cp: The start of the string
52 * @endp: A pointer to the end of the parsed string will be placed here
53 * @base: The number base to use
55 long simple_strtol(const char *cp,char **endp,unsigned int base)
58 return -simple_strtoul(cp+1,endp,base);
59 return simple_strtoul(cp,endp,base);
63 * simple_strtoull - convert a string to an unsigned long long
64 * @cp: The start of the string
65 * @endp: A pointer to the end of the parsed string will be placed here
66 * @base: The number base to use
68 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
70 unsigned long long result = 0,value;
77 if ((*cp == 'x') && isxdigit(cp[1])) {
83 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
84 ? toupper(*cp) : *cp)-'A'+10) < base) {
85 result = result*base + value;
94 * simple_strtoll - convert a string to a signed long long
95 * @cp: The start of the string
96 * @endp: A pointer to the end of the parsed string will be placed here
97 * @base: The number base to use
99 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
102 return -simple_strtoull(cp+1,endp,base);
103 return simple_strtoull(cp,endp,base);
106 static int skip_atoi(const char **s)
111 i = i*10 + *((*s)++) - '0';
115 #define ZEROPAD 1 /* pad with zero */
116 #define SIGN 2 /* unsigned/signed long */
117 #define PLUS 4 /* show plus */
118 #define SPACE 8 /* space if plus */
119 #define LEFT 16 /* left justified */
120 #define SPECIAL 32 /* 0x */
121 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
123 static char * number(char * str, long long num, int base, int size, int precision, int type)
126 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
130 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
133 if (base < 2 || base > 36)
135 c = (type & ZEROPAD) ? '0' : ' ';
142 } else if (type & PLUS) {
145 } else if (type & SPACE) {
150 if (type & SPECIAL) {
159 else while (num != 0)
161 int t = ((long long) num) % (unsigned int) base;
162 tmp[i++] = digits[t];
163 num = ((long long) num) / (unsigned int) base;
168 if (!(type&(ZEROPAD+LEFT)))
173 if (type & SPECIAL) {
184 while (i < precision--)
194 * vsprintf - Format a string and place it in a buffer
195 * @buf: The buffer to place the result into
196 * @fmt: The format string to use
197 * @args: Arguments for the format string
199 * Call this function if you are already dealing with a va_list.
200 * You probably want sprintf instead.
202 int vsprintf(char *buf, const char *fmt, va_list args)
205 unsigned long long num;
210 int flags; /* flags to number() */
212 int field_width; /* width of output field */
213 int precision; /* min. # of digits for integers; max
214 number of chars for from string */
215 int qualifier; /* 'h', 'l', or 'L' for integer fields */
216 /* 'z' support added 23/7/1999 S.H. */
217 /* 'z' changed to 'Z' --davidm 1/25/99 */
220 for (str=buf ; *fmt ; ++fmt) {
229 ++fmt; /* this also skips first '%' */
231 case '-': flags |= LEFT; goto repeat;
232 case '+': flags |= PLUS; goto repeat;
233 case ' ': flags |= SPACE; goto repeat;
234 case '#': flags |= SPECIAL; goto repeat;
235 case '0': flags |= ZEROPAD; goto repeat;
238 /* get field width */
241 field_width = skip_atoi(&fmt);
242 else if (*fmt == '*') {
244 /* it's the next argument */
245 field_width = va_arg(args, int);
246 if (field_width < 0) {
247 field_width = -field_width;
252 /* get the precision */
257 precision = skip_atoi(&fmt);
258 else if (*fmt == '*') {
260 /* it's the next argument */
261 precision = va_arg(args, int);
267 /* get the conversion qualifier */
269 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
280 while (--field_width > 0)
282 *str++ = (unsigned char) va_arg(args, int);
283 while (--field_width > 0)
288 s = va_arg(args, char *);
292 len = strnlen(s, precision);
295 while (len < field_width--)
297 for (i = 0; i < len; ++i)
299 while (len < field_width--)
304 if (field_width == -1) {
305 field_width = 2*sizeof(void *);
309 (unsigned long) va_arg(args, void *), 16,
310 field_width, precision, flags);
315 if (qualifier == 'l') {
316 long * ip = va_arg(args, long *);
318 } else if (qualifier == 'Z') {
319 size_t * ip = va_arg(args, size_t *);
322 int * ip = va_arg(args, int *);
331 /* integer number formats - set up the flags and "break" */
356 if (qualifier == 'L') {
357 num = va_arg(args, unsigned long long);
359 num = (signed long long) num;
360 } else if (qualifier == 'l') {
361 num = va_arg(args, unsigned long);
363 num = (signed long) num;
364 } else if (qualifier == 'Z') {
365 num = va_arg(args, size_t);
366 } else if (qualifier == 'h') {
367 num = (unsigned short) va_arg(args, int);
369 num = (signed short) num;
371 num = va_arg(args, unsigned int);
373 num = (signed int) num;
375 str = number(str, num, base, field_width, precision, flags);
382 * sprintf - Format a string and place it in a buffer
383 * @buf: The buffer to place the result into
384 * @fmt: The format string to use
385 * @...: Arguments for the format string
387 int sprintf(char * buf, const char *fmt, ...)
393 i=vsprintf(buf,fmt,args);