ia64/xen-unstable

view xen/common/vsprintf.c @ 9706:3c05406f5e0a

In some cases, say for instance for some bizzare reason
the tree was checked out of CVS, which doens't neccessarily
store file permissions, mkbuildtree may not be executable.
So run them explicitly via bash.

Signed-Off-By: Horms <horms@verge.net.au>
author kaf24@firebug.cl.cam.ac.uk
date Thu Apr 13 11:24:00 2006 +0100 (2006-04-13)
parents b866ed85fad3
children 3409c35a0b0e
line source
1 /*
2 * linux/lib/vsprintf.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10 */
12 /*
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
17 */
19 #include <stdarg.h>
20 #include <xen/ctype.h>
21 #include <xen/lib.h>
22 #include <asm/div64.h>
23 #include <asm/page.h>
25 /**
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
30 */
31 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
32 {
33 unsigned long result = 0,value;
35 if (!base) {
36 base = 10;
37 if (*cp == '0') {
38 base = 8;
39 cp++;
40 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
41 cp++;
42 base = 16;
43 }
44 }
45 } else if (base == 16) {
46 if (cp[0] == '0' && toupper(cp[1]) == 'X')
47 cp += 2;
48 }
49 while (isxdigit(*cp) &&
50 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
51 result = result*base + value;
52 cp++;
53 }
54 if (endp)
55 *endp = (char *)cp;
56 return result;
57 }
59 EXPORT_SYMBOL(simple_strtoul);
61 /**
62 * simple_strtol - convert a string to a signed long
63 * @cp: The start of the string
64 * @endp: A pointer to the end of the parsed string will be placed here
65 * @base: The number base to use
66 */
67 long simple_strtol(const char *cp,char **endp,unsigned int base)
68 {
69 if(*cp=='-')
70 return -simple_strtoul(cp+1,endp,base);
71 return simple_strtoul(cp,endp,base);
72 }
74 EXPORT_SYMBOL(simple_strtol);
76 /**
77 * simple_strtoull - convert a string to an unsigned long long
78 * @cp: The start of the string
79 * @endp: A pointer to the end of the parsed string will be placed here
80 * @base: The number base to use
81 */
82 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
83 {
84 unsigned long long result = 0,value;
86 if (!base) {
87 base = 10;
88 if (*cp == '0') {
89 base = 8;
90 cp++;
91 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
92 cp++;
93 base = 16;
94 }
95 }
96 } else if (base == 16) {
97 if (cp[0] == '0' && toupper(cp[1]) == 'X')
98 cp += 2;
99 }
100 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
101 ? toupper(*cp) : *cp)-'A'+10) < base) {
102 result = result*base + value;
103 cp++;
104 }
105 if (endp)
106 *endp = (char *)cp;
107 return result;
108 }
110 EXPORT_SYMBOL(simple_strtoull);
112 /**
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
117 */
118 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
119 {
120 if(*cp=='-')
121 return -simple_strtoull(cp+1,endp,base);
122 return simple_strtoull(cp,endp,base);
123 }
125 static int skip_atoi(const char **s)
126 {
127 int i=0;
129 while (isdigit(**s))
130 i = i*10 + *((*s)++) - '0';
131 return i;
132 }
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)
143 {
144 char c,sign,tmp[66];
145 const char *digits;
146 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
147 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
148 int i;
150 digits = (type & LARGE) ? large_digits : small_digits;
151 if (type & LEFT)
152 type &= ~ZEROPAD;
153 if (base < 2 || base > 36)
154 return NULL;
155 c = (type & ZEROPAD) ? '0' : ' ';
156 sign = 0;
157 if (type & SIGN) {
158 if ((signed long long) num < 0) {
159 sign = '-';
160 num = - (signed long long) num;
161 size--;
162 } else if (type & PLUS) {
163 sign = '+';
164 size--;
165 } else if (type & SPACE) {
166 sign = ' ';
167 size--;
168 }
169 }
170 if (type & SPECIAL) {
171 if (base == 16)
172 size -= 2;
173 else if (base == 8)
174 size--;
175 }
176 i = 0;
177 if (num == 0)
178 tmp[i++]='0';
179 else while (num != 0)
180 tmp[i++] = digits[do_div(num,base)];
181 #if 0
182 else
183 {
184 /* XXX KAF: force unsigned mod and div. */
185 unsigned long long num2=(unsigned long long)num;
186 unsigned int base2=(unsigned int)base;
187 while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
188 }
189 #endif
190 if (i > precision)
191 precision = i;
192 size -= precision;
193 if (!(type&(ZEROPAD+LEFT))) {
194 while(size-->0) {
195 if (buf <= end)
196 *buf = ' ';
197 ++buf;
198 }
199 }
200 if (sign) {
201 if (buf <= end)
202 *buf = sign;
203 ++buf;
204 }
205 if (type & SPECIAL) {
206 if (base==8) {
207 if (buf <= end)
208 *buf = '0';
209 ++buf;
210 } else if (base==16) {
211 if (buf <= end)
212 *buf = '0';
213 ++buf;
214 if (buf <= end)
215 *buf = digits[33];
216 ++buf;
217 }
218 }
219 if (!(type & LEFT)) {
220 while (size-- > 0) {
221 if (buf <= end)
222 *buf = c;
223 ++buf;
224 }
225 }
226 while (i < precision--) {
227 if (buf <= end)
228 *buf = '0';
229 ++buf;
230 }
231 while (i-- > 0) {
232 if (buf <= end)
233 *buf = tmp[i];
234 ++buf;
235 }
236 while (size-- > 0) {
237 if (buf <= end)
238 *buf = ' ';
239 ++buf;
240 }
241 return buf;
242 }
244 /**
245 * vsnprintf - Format a string and place it in a buffer
246 * @buf: The buffer to place the result into
247 * @size: The size of the buffer, including the trailing null space
248 * @fmt: The format string to use
249 * @args: Arguments for the format string
250 *
251 * The return value is the number of characters which would
252 * be generated for the given input, excluding the trailing
253 * '\0', as per ISO C99. If you want to have the exact
254 * number of characters written into @buf as return value
255 * (not including the trailing '\0'), use vscnprintf. If the
256 * return is greater than or equal to @size, the resulting
257 * string is truncated.
258 *
259 * Call this function if you are already dealing with a va_list.
260 * You probably want snprintf instead.
261 */
262 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
263 {
264 int len;
265 unsigned long long num;
266 int i, base;
267 char *str, *end, c;
268 const char *s;
270 int flags; /* flags to number() */
272 int field_width; /* width of output field */
273 int precision; /* min. # of digits for integers; max
274 number of chars for from string */
275 int qualifier; /* 'h', 'l', or 'L' for integer fields */
276 /* 'z' support added 23/7/1999 S.H. */
277 /* 'z' changed to 'Z' --davidm 1/25/99 */
279 /* Reject out-of-range values early */
280 BUG_ON((int)size < 0);
282 str = buf;
283 end = buf + size - 1;
285 if (end < buf - 1) {
286 end = ((void *) -1);
287 size = end - buf + 1;
288 }
290 for (; *fmt ; ++fmt) {
291 if (*fmt != '%') {
292 if (str <= end)
293 *str = *fmt;
294 ++str;
295 continue;
296 }
298 /* process flags */
299 flags = 0;
300 repeat:
301 ++fmt; /* this also skips first '%' */
302 switch (*fmt) {
303 case '-': flags |= LEFT; goto repeat;
304 case '+': flags |= PLUS; goto repeat;
305 case ' ': flags |= SPACE; goto repeat;
306 case '#': flags |= SPECIAL; goto repeat;
307 case '0': flags |= ZEROPAD; goto repeat;
308 }
310 /* get field width */
311 field_width = -1;
312 if (isdigit(*fmt))
313 field_width = skip_atoi(&fmt);
314 else if (*fmt == '*') {
315 ++fmt;
316 /* it's the next argument */
317 field_width = va_arg(args, int);
318 if (field_width < 0) {
319 field_width = -field_width;
320 flags |= LEFT;
321 }
322 }
324 /* get the precision */
325 precision = -1;
326 if (*fmt == '.') {
327 ++fmt;
328 if (isdigit(*fmt))
329 precision = skip_atoi(&fmt);
330 else if (*fmt == '*') {
331 ++fmt;
332 /* it's the next argument */
333 precision = va_arg(args, int);
334 }
335 if (precision < 0)
336 precision = 0;
337 }
339 /* get the conversion qualifier */
340 qualifier = -1;
341 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
342 *fmt =='Z' || *fmt == 'z') {
343 qualifier = *fmt;
344 ++fmt;
345 if (qualifier == 'l' && *fmt == 'l') {
346 qualifier = 'L';
347 ++fmt;
348 }
349 }
351 /* default base */
352 base = 10;
354 switch (*fmt) {
355 case 'c':
356 if (!(flags & LEFT)) {
357 while (--field_width > 0) {
358 if (str <= end)
359 *str = ' ';
360 ++str;
361 }
362 }
363 c = (unsigned char) va_arg(args, int);
364 if (str <= end)
365 *str = c;
366 ++str;
367 while (--field_width > 0) {
368 if (str <= end)
369 *str = ' ';
370 ++str;
371 }
372 continue;
374 case 's':
375 s = va_arg(args, char *);
376 if ((unsigned long)s < PAGE_SIZE)
377 s = "<NULL>";
379 len = strnlen(s, precision);
381 if (!(flags & LEFT)) {
382 while (len < field_width--) {
383 if (str <= end)
384 *str = ' ';
385 ++str;
386 }
387 }
388 for (i = 0; i < len; ++i) {
389 if (str <= end)
390 *str = *s;
391 ++str; ++s;
392 }
393 while (len < field_width--) {
394 if (str <= end)
395 *str = ' ';
396 ++str;
397 }
398 continue;
400 case 'p':
401 if (field_width == -1) {
402 field_width = 2*sizeof(void *);
403 flags |= ZEROPAD;
404 }
405 str = number(str, end,
406 (unsigned long) va_arg(args, void *),
407 16, field_width, precision, flags);
408 continue;
411 case 'n':
412 /* FIXME:
413 * What does C99 say about the overflow case here? */
414 if (qualifier == 'l') {
415 long * ip = va_arg(args, long *);
416 *ip = (str - buf);
417 } else if (qualifier == 'Z' || qualifier == 'z') {
418 size_t * ip = va_arg(args, size_t *);
419 *ip = (str - buf);
420 } else {
421 int * ip = va_arg(args, int *);
422 *ip = (str - buf);
423 }
424 continue;
426 case '%':
427 if (str <= end)
428 *str = '%';
429 ++str;
430 continue;
432 /* integer number formats - set up the flags and "break" */
433 case 'o':
434 base = 8;
435 break;
437 case 'X':
438 flags |= LARGE;
439 case 'x':
440 base = 16;
441 break;
443 case 'd':
444 case 'i':
445 flags |= SIGN;
446 case 'u':
447 break;
449 default:
450 if (str <= end)
451 *str = '%';
452 ++str;
453 if (*fmt) {
454 if (str <= end)
455 *str = *fmt;
456 ++str;
457 } else {
458 --fmt;
459 }
460 continue;
461 }
462 if (qualifier == 'L')
463 num = va_arg(args, long long);
464 else if (qualifier == 'l') {
465 num = va_arg(args, unsigned long);
466 if (flags & SIGN)
467 num = (signed long) num;
468 } else if (qualifier == 'Z' || qualifier == 'z') {
469 num = va_arg(args, size_t);
470 } else if (qualifier == 'h') {
471 num = (unsigned short) va_arg(args, int);
472 if (flags & SIGN)
473 num = (signed short) num;
474 } else {
475 num = va_arg(args, unsigned int);
476 if (flags & SIGN)
477 num = (signed int) num;
478 }
480 str = number(str, end, num, base,
481 field_width, precision, flags);
482 }
483 if (str <= end)
484 *str = '\0';
485 else if (size > 0)
486 /* don't write out a null byte if the buf size is zero */
487 *end = '\0';
488 /* the trailing null byte doesn't count towards the total
489 * ++str;
490 */
491 return str-buf;
492 }
494 EXPORT_SYMBOL(vsnprintf);
496 /**
497 * vscnprintf - Format a string and place it in a buffer
498 * @buf: The buffer to place the result into
499 * @size: The size of the buffer, including the trailing null space
500 * @fmt: The format string to use
501 * @args: Arguments for the format string
502 *
503 * The return value is the number of characters which have been written into
504 * the @buf not including the trailing '\0'. If @size is <= 0 the function
505 * returns 0.
506 *
507 * Call this function if you are already dealing with a va_list.
508 * You probably want scnprintf instead.
509 */
510 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
511 {
512 int i;
514 i=vsnprintf(buf,size,fmt,args);
515 return (i >= size) ? (size - 1) : i;
516 }
518 EXPORT_SYMBOL(vscnprintf);
520 /**
521 * snprintf - Format a string and place it in a buffer
522 * @buf: The buffer to place the result into
523 * @size: The size of the buffer, including the trailing null space
524 * @fmt: The format string to use
525 * @...: Arguments for the format string
526 *
527 * The return value is the number of characters which would be
528 * generated for the given input, excluding the trailing null,
529 * as per ISO C99. If the return is greater than or equal to
530 * @size, the resulting string is truncated.
531 */
532 int snprintf(char * buf, size_t size, const char *fmt, ...)
533 {
534 va_list args;
535 int i;
537 va_start(args, fmt);
538 i=vsnprintf(buf,size,fmt,args);
539 va_end(args);
540 return i;
541 }
543 EXPORT_SYMBOL(snprintf);
545 /**
546 * scnprintf - Format a string and place it in a buffer
547 * @buf: The buffer to place the result into
548 * @size: The size of the buffer, including the trailing null space
549 * @fmt: The format string to use
550 * @...: Arguments for the format string
551 *
552 * The return value is the number of characters written into @buf not including
553 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
554 * greater than or equal to @size, the resulting string is truncated.
555 */
557 int scnprintf(char * buf, size_t size, const char *fmt, ...)
558 {
559 va_list args;
560 int i;
562 va_start(args, fmt);
563 i = vsnprintf(buf, size, fmt, args);
564 va_end(args);
565 return (i >= size) ? (size - 1) : i;
566 }
567 EXPORT_SYMBOL(scnprintf);
569 /**
570 * vsprintf - Format a string and place it in a buffer
571 * @buf: The buffer to place the result into
572 * @fmt: The format string to use
573 * @args: Arguments for the format string
574 *
575 * The function returns the number of characters written
576 * into @buf. Use vsnprintf or vscnprintf in order to avoid
577 * buffer overflows.
578 *
579 * Call this function if you are already dealing with a va_list.
580 * You probably want sprintf instead.
581 */
582 int vsprintf(char *buf, const char *fmt, va_list args)
583 {
584 return vsnprintf(buf, INT_MAX, fmt, args);
585 }
587 EXPORT_SYMBOL(vsprintf);
589 /**
590 * sprintf - Format a string and place it in a buffer
591 * @buf: The buffer to place the result into
592 * @fmt: The format string to use
593 * @...: Arguments for the format string
594 *
595 * The function returns the number of characters written
596 * into @buf. Use snprintf or scnprintf in order to avoid
597 * buffer overflows.
598 */
599 int sprintf(char * buf, const char *fmt, ...)
600 {
601 va_list args;
602 int i;
604 va_start(args, fmt);
605 i=vsnprintf(buf, INT_MAX, fmt, args);
606 va_end(args);
607 return i;
608 }
610 EXPORT_SYMBOL(sprintf);
612 /*
613 * Local variables:
614 * mode: C
615 * c-set-style: "BSD"
616 * c-basic-offset: 4
617 * tab-width: 4
618 * indent-tabs-mode: nil
619 * End:
620 */