~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/lib/vsprintf.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/lib/vsprintf.c
  3  *
  4  *  Copyright (C) 1991, 1992  Linus Torvalds
  5  */
  6 
  7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  8 /*
  9  * Wirzenius wrote this portably, Torvalds fucked it up :-)
 10  */
 11 
 12 #include <stdarg.h>
 13 #include <linux/types.h>
 14 #include <linux/string.h>
 15 #include <linux/ctype.h>
 16 
 17 #include <asm/div64.h>
 18 
 19 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
 20 {
 21         unsigned long result = 0,value;
 22 
 23         if (!base) {
 24                 base = 10;
 25                 if (*cp == '') {
 26                         base = 8;
 27                         cp++;
 28                         if ((*cp == 'x') && isxdigit(cp[1])) {
 29                                 cp++;
 30                                 base = 16;
 31                         }
 32                 }
 33         }
 34         while (isxdigit(*cp) &&
 35                (value = isdigit(*cp) ? *cp-'' : toupper(*cp)-'A'+10) < base) {
 36                 result = result*base + value;
 37                 cp++;
 38         }
 39         if (endp)
 40                 *endp = (char *)cp;
 41         return result;
 42 }
 43 
 44 long simple_strtol(const char *cp,char **endp,unsigned int base)
 45 {
 46         if(*cp=='-')
 47                 return -simple_strtoul(cp+1,endp,base);
 48         return simple_strtoul(cp,endp,base);
 49 }
 50 
 51 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
 52 {
 53         unsigned long long result = 0,value;
 54 
 55         if (!base) {
 56                 base = 10;
 57                 if (*cp == '') {
 58                         base = 8;
 59                         cp++;
 60                         if ((*cp == 'x') && isxdigit(cp[1])) {
 61                                 cp++;
 62                                 base = 16;
 63                         }
 64                 }
 65         }
 66         while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'' : (islower(*cp)
 67             ? toupper(*cp) : *cp)-'A'+10) < base) {
 68                 result = result*base + value;
 69                 cp++;
 70         }
 71         if (endp)
 72                 *endp = (char *)cp;
 73         return result;
 74 }
 75 
 76 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
 77 {
 78         if(*cp=='-')
 79                 return -simple_strtoull(cp+1,endp,base);
 80         return simple_strtoull(cp,endp,base);
 81 }
 82 
 83 static int skip_atoi(const char **s)
 84 {
 85         int i=0;
 86 
 87         while (isdigit(**s))
 88                 i = i*10 + *((*s)++) - '';
 89         return i;
 90 }
 91 
 92 #define ZEROPAD 1               /* pad with zero */
 93 #define SIGN    2               /* unsigned/signed long */
 94 #define PLUS    4               /* show plus */
 95 #define SPACE   8               /* space if plus */
 96 #define LEFT    16              /* left justified */
 97 #define SPECIAL 32              /* 0x */
 98 #define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
 99 
100 static char * number(char * str, long long num, int base, int size, int precision, int type)
101 {
102         char c,sign,tmp[66];
103         const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
104         int i;
105 
106         if (type & LARGE)
107                 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
108         if (type & LEFT)
109                 type &= ~ZEROPAD;
110         if (base < 2 || base > 36)
111                 return 0;
112         c = (type & ZEROPAD) ? '' : ' ';
113         sign = 0;
114         if (type & SIGN) {
115                 if (num < 0) {
116                         sign = '-';
117                         num = -num;
118                         size--;
119                 } else if (type & PLUS) {
120                         sign = '+';
121                         size--;
122                 } else if (type & SPACE) {
123                         sign = ' ';
124                         size--;
125                 }
126         }
127         if (type & SPECIAL) {
128                 if (base == 16)
129                         size -= 2;
130                 else if (base == 8)
131                         size--;
132         }
133         i = 0;
134         if (num == 0)
135                 tmp[i++]='';
136         else while (num != 0)
137                 tmp[i++] = digits[do_div(num,base)];
138         if (i > precision)
139                 precision = i;
140         size -= precision;
141         if (!(type&(ZEROPAD+LEFT)))
142                 while(size-->0)
143                         *str++ = ' ';
144         if (sign)
145                 *str++ = sign;
146         if (type & SPECIAL) {
147                 if (base==8)
148                         *str++ = '';
149                 else if (base==16) {
150                         *str++ = '';
151                         *str++ = digits[33];
152                 }
153         }
154         if (!(type & LEFT))
155                 while (size-- > 0)
156                         *str++ = c;
157         while (i < precision--)
158                 *str++ = '';
159         while (i-- > 0)
160                 *str++ = tmp[i];
161         while (size-- > 0)
162                 *str++ = ' ';
163         return str;
164 }
165 
166 /* Forward decl. needed for IP address printing stuff... */
167 int sprintf(char * buf, const char *fmt, ...);
168 
169 int vsprintf(char *buf, const char *fmt, va_list args)
170 {
171         int len;
172         unsigned long long num;
173         int i, base;
174         char * str;
175         const char *s;
176 
177         int flags;              /* flags to number() */
178 
179         int field_width;        /* width of output field */
180         int precision;          /* min. # of digits for integers; max
181                                    number of chars for from string */
182         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
183                                 /* 'z' support added 23/7/1999 S.H.    */
184                                 /* 'z' changed to 'Z' --davidm 1/25/99 */
185 
186         
187         for (str=buf ; *fmt ; ++fmt) {
188                 if (*fmt != '%') {
189                         *str++ = *fmt;
190                         continue;
191                 }
192                         
193                 /* process flags */
194                 flags = 0;
195                 repeat:
196                         ++fmt;          /* this also skips first '%' */
197                         switch (*fmt) {
198                                 case '-': flags |= LEFT; goto repeat;
199                                 case '+': flags |= PLUS; goto repeat;
200                                 case ' ': flags |= SPACE; goto repeat;
201                                 case '#': flags |= SPECIAL; goto repeat;
202                                 case '': flags |= ZEROPAD; goto repeat;
203                                 }
204                 
205                 /* get field width */
206                 field_width = -1;
207                 if (isdigit(*fmt))
208                         field_width = skip_atoi(&fmt);
209                 else if (*fmt == '*') {
210                         ++fmt;
211                         /* it's the next argument */
212                         field_width = va_arg(args, int);
213                         if (field_width < 0) {
214                                 field_width = -field_width;
215                                 flags |= LEFT;
216                         }
217                 }
218 
219                 /* get the precision */
220                 precision = -1;
221                 if (*fmt == '.') {
222                         ++fmt;  
223                         if (isdigit(*fmt))
224                                 precision = skip_atoi(&fmt);
225                         else if (*fmt == '*') {
226                                 ++fmt;
227                                 /* it's the next argument */
228                                 precision = va_arg(args, int);
229                         }
230                         if (precision < 0)
231                                 precision = 0;
232                 }
233 
234                 /* get the conversion qualifier */
235                 qualifier = -1;
236                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
237                         qualifier = *fmt;
238                         ++fmt;
239                 }
240 
241                 /* default base */
242                 base = 10;
243 
244                 switch (*fmt) {
245                 case 'c':
246                         if (!(flags & LEFT))
247                                 while (--field_width > 0)
248                                         *str++ = ' ';
249                         *str++ = (unsigned char) va_arg(args, int);
250                         while (--field_width > 0)
251                                 *str++ = ' ';
252                         continue;
253 
254                 case 's':
255                         s = va_arg(args, char *);
256                         if (!s)
257                                 s = "<NULL>";
258 
259                         len = strnlen(s, precision);
260 
261                         if (!(flags & LEFT))
262                                 while (len < field_width--)
263                                         *str++ = ' ';
264                         for (i = 0; i < len; ++i)
265                                 *str++ = *s++;
266                         while (len < field_width--)
267                                 *str++ = ' ';
268                         continue;
269 
270                 case 'p':
271                         if (field_width == -1) {
272                                 field_width = 2*sizeof(void *);
273                                 flags |= ZEROPAD;
274                         }
275                         str = number(str,
276                                 (unsigned long) va_arg(args, void *), 16,
277                                 field_width, precision, flags);
278                         continue;
279 
280 
281                 case 'n':
282                         if (qualifier == 'l') {
283                                 long * ip = va_arg(args, long *);
284                                 *ip = (str - buf);
285                         } else if (qualifier == 'Z') {
286                                 size_t * ip = va_arg(args, size_t *);
287                                 *ip = (str - buf);
288                         } else {
289                                 int * ip = va_arg(args, int *);
290                                 *ip = (str - buf);
291                         }
292                         continue;
293 
294                 case '%':
295                         *str++ = '%';
296                         continue;
297 
298                 /* integer number formats - set up the flags and "break" */
299                 case 'o':
300                         base = 8;
301                         break;
302 
303                 case 'X':
304                         flags |= LARGE;
305                 case 'x':
306                         base = 16;
307                         break;
308 
309                 case 'd':
310                 case 'i':
311                         flags |= SIGN;
312                 case 'u':
313                         break;
314 
315                 default:
316                         *str++ = '%';
317                         if (*fmt)
318                                 *str++ = *fmt;
319                         else
320                                 --fmt;
321                         continue;
322                 }
323                 if (qualifier == 'L')
324                         num = va_arg(args, long long);
325                 else if (qualifier == 'l') {
326                         num = va_arg(args, unsigned long);
327                         if (flags & SIGN)
328                                 num = (signed long) num;
329                 } else if (qualifier == 'Z') {
330                         num = va_arg(args, size_t);
331                 } else if (qualifier == 'h') {
332                         num = (unsigned short) va_arg(args, int);
333                         if (flags & SIGN)
334                                 num = (signed short) num;
335                 } else {
336                         num = va_arg(args, unsigned int);
337                         if (flags & SIGN)
338                                 num = (signed int) num;
339                 }
340                 str = number(str, num, base, field_width, precision, flags);
341         }
342         *str = '\0';
343         return str-buf;
344 }
345 
346 int sprintf(char * buf, const char *fmt, ...)
347 {
348         va_list args;
349         int i;
350 
351         va_start(args, fmt);
352         i=vsprintf(buf,fmt,args);
353         va_end(args);
354         return i;
355 }
356 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.