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