ia64/xen-unstable

view xen/common/vsprintf.c @ 17062:0769835cf50f

x86 shadow: Reduce scope of shadow lock.

emulate_map_dest doesn't require holding lock, since
only shadow related operation possibly involved is to
remove shadow which is less frequent and can acquire
lock inside. Rest are either guest table walk or
per-vcpu monitor table manipulation

Signed-off-by Kevin Tian <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 14 10:33:12 2008 +0000 (2008-02-14)
parents 19f549449cb5
children 40233384ffe3
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 <xen/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(
32 const char *cp, const char **endp, unsigned int base)
33 {
34 unsigned long result = 0,value;
36 if (!base) {
37 base = 10;
38 if (*cp == '0') {
39 base = 8;
40 cp++;
41 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
42 cp++;
43 base = 16;
44 }
45 }
46 } else if (base == 16) {
47 if (cp[0] == '0' && toupper(cp[1]) == 'X')
48 cp += 2;
49 }
50 while (isxdigit(*cp) &&
51 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
52 result = result*base + value;
53 cp++;
54 }
55 if (endp)
56 *endp = cp;
57 return result;
58 }
60 EXPORT_SYMBOL(simple_strtoul);
62 /**
63 * simple_strtol - convert a string to a signed 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
67 */
68 long simple_strtol(const char *cp, const char **endp, unsigned int base)
69 {
70 if(*cp=='-')
71 return -simple_strtoul(cp+1,endp,base);
72 return simple_strtoul(cp,endp,base);
73 }
75 EXPORT_SYMBOL(simple_strtol);
77 /**
78 * simple_strtoull - convert a string to an unsigned long long
79 * @cp: The start of the string
80 * @endp: A pointer to the end of the parsed string will be placed here
81 * @base: The number base to use
82 */
83 unsigned long long simple_strtoull(
84 const char *cp, const char **endp, unsigned int base)
85 {
86 unsigned long long result = 0,value;
88 if (!base) {
89 base = 10;
90 if (*cp == '0') {
91 base = 8;
92 cp++;
93 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
94 cp++;
95 base = 16;
96 }
97 }
98 } else if (base == 16) {
99 if (cp[0] == '0' && toupper(cp[1]) == 'X')
100 cp += 2;
101 }
102 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
103 ? toupper(*cp) : *cp)-'A'+10) < base) {
104 result = result*base + value;
105 cp++;
106 }
107 if (endp)
108 *endp = cp;
109 return result;
110 }
112 EXPORT_SYMBOL(simple_strtoull);
114 /**
115 * simple_strtoll - convert a string to a signed long long
116 * @cp: The start of the string
117 * @endp: A pointer to the end of the parsed string will be placed here
118 * @base: The number base to use
119 */
120 long long simple_strtoll(const char *cp,const char **endp,unsigned int base)
121 {
122 if(*cp=='-')
123 return -simple_strtoull(cp+1,endp,base);
124 return simple_strtoull(cp,endp,base);
125 }
127 static int skip_atoi(const char **s)
128 {
129 int i=0;
131 while (isdigit(**s))
132 i = i*10 + *((*s)++) - '0';
133 return i;
134 }
136 #define ZEROPAD 1 /* pad with zero */
137 #define SIGN 2 /* unsigned/signed long */
138 #define PLUS 4 /* show plus */
139 #define SPACE 8 /* space if plus */
140 #define LEFT 16 /* left justified */
141 #define SPECIAL 32 /* 0x */
142 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
144 static char *number(
145 char *buf, char *end, unsigned long long num,
146 int base, int size, int precision, int type)
147 {
148 char c,sign,tmp[66];
149 const char *digits;
150 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
151 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
152 int i;
154 digits = (type & LARGE) ? large_digits : small_digits;
155 if (type & LEFT)
156 type &= ~ZEROPAD;
157 if (base < 2 || base > 36)
158 return NULL;
159 c = (type & ZEROPAD) ? '0' : ' ';
160 sign = 0;
161 if (type & SIGN) {
162 if ((signed long long) num < 0) {
163 sign = '-';
164 num = - (signed long long) num;
165 size--;
166 } else if (type & PLUS) {
167 sign = '+';
168 size--;
169 } else if (type & SPACE) {
170 sign = ' ';
171 size--;
172 }
173 }
174 if (type & SPECIAL) {
175 if (base == 16)
176 size -= 2;
177 else if (base == 8)
178 size--;
179 }
180 i = 0;
181 if (num == 0)
182 tmp[i++]='0';
183 else while (num != 0)
184 tmp[i++] = digits[do_div(num,base)];
185 if (i > precision)
186 precision = i;
187 size -= precision;
188 if (!(type&(ZEROPAD+LEFT))) {
189 while(size-->0) {
190 if (buf <= end)
191 *buf = ' ';
192 ++buf;
193 }
194 }
195 if (sign) {
196 if (buf <= end)
197 *buf = sign;
198 ++buf;
199 }
200 if (type & SPECIAL) {
201 if (base==8) {
202 if (buf <= end)
203 *buf = '0';
204 ++buf;
205 } else if (base==16) {
206 if (buf <= end)
207 *buf = '0';
208 ++buf;
209 if (buf <= end)
210 *buf = digits[33];
211 ++buf;
212 }
213 }
214 if (!(type & LEFT)) {
215 while (size-- > 0) {
216 if (buf <= end)
217 *buf = c;
218 ++buf;
219 }
220 }
221 while (i < precision--) {
222 if (buf <= end)
223 *buf = '0';
224 ++buf;
225 }
226 while (i-- > 0) {
227 if (buf <= end)
228 *buf = tmp[i];
229 ++buf;
230 }
231 while (size-- > 0) {
232 if (buf <= end)
233 *buf = ' ';
234 ++buf;
235 }
236 return buf;
237 }
239 /**
240 * vsnprintf - Format a string and place it in a buffer
241 * @buf: The buffer to place the result into
242 * @size: The size of the buffer, including the trailing null space
243 * @fmt: The format string to use
244 * @args: Arguments for the format string
245 *
246 * The return value is the number of characters which would
247 * be generated for the given input, excluding the trailing
248 * '\0', as per ISO C99. If you want to have the exact
249 * number of characters written into @buf as return value
250 * (not including the trailing '\0'), use vscnprintf. If the
251 * return is greater than or equal to @size, the resulting
252 * string is truncated.
253 *
254 * Call this function if you are already dealing with a va_list.
255 * You probably want snprintf instead.
256 */
257 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
258 {
259 int len;
260 unsigned long long num;
261 int i, base;
262 char *str, *end, c;
263 const char *s;
265 int flags; /* flags to number() */
267 int field_width; /* width of output field */
268 int precision; /* min. # of digits for integers; max
269 number of chars for from string */
270 int qualifier; /* 'h', 'l', or 'L' for integer fields */
271 /* 'z' support added 23/7/1999 S.H. */
272 /* 'z' changed to 'Z' --davidm 1/25/99 */
274 /* Reject out-of-range values early */
275 BUG_ON((int)size < 0);
277 str = buf;
278 end = buf + size - 1;
280 if (end < buf - 1) {
281 end = ((void *) -1);
282 size = end - buf + 1;
283 }
285 for (; *fmt ; ++fmt) {
286 if (*fmt != '%') {
287 if (str <= end)
288 *str = *fmt;
289 ++str;
290 continue;
291 }
293 /* process flags */
294 flags = 0;
295 repeat:
296 ++fmt; /* this also skips first '%' */
297 switch (*fmt) {
298 case '-': flags |= LEFT; goto repeat;
299 case '+': flags |= PLUS; goto repeat;
300 case ' ': flags |= SPACE; goto repeat;
301 case '#': flags |= SPECIAL; goto repeat;
302 case '0': flags |= ZEROPAD; goto repeat;
303 }
305 /* get field width */
306 field_width = -1;
307 if (isdigit(*fmt))
308 field_width = skip_atoi(&fmt);
309 else if (*fmt == '*') {
310 ++fmt;
311 /* it's the next argument */
312 field_width = va_arg(args, int);
313 if (field_width < 0) {
314 field_width = -field_width;
315 flags |= LEFT;
316 }
317 }
319 /* get the precision */
320 precision = -1;
321 if (*fmt == '.') {
322 ++fmt;
323 if (isdigit(*fmt))
324 precision = skip_atoi(&fmt);
325 else if (*fmt == '*') {
326 ++fmt;
327 /* it's the next argument */
328 precision = va_arg(args, int);
329 }
330 if (precision < 0)
331 precision = 0;
332 }
334 /* get the conversion qualifier */
335 qualifier = -1;
336 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
337 *fmt =='Z' || *fmt == 'z') {
338 qualifier = *fmt;
339 ++fmt;
340 if (qualifier == 'l' && *fmt == 'l') {
341 qualifier = 'L';
342 ++fmt;
343 }
344 }
346 /* default base */
347 base = 10;
349 switch (*fmt) {
350 case 'c':
351 if (!(flags & LEFT)) {
352 while (--field_width > 0) {
353 if (str <= end)
354 *str = ' ';
355 ++str;
356 }
357 }
358 c = (unsigned char) va_arg(args, int);
359 if (str <= end)
360 *str = c;
361 ++str;
362 while (--field_width > 0) {
363 if (str <= end)
364 *str = ' ';
365 ++str;
366 }
367 continue;
369 case 's':
370 s = va_arg(args, char *);
371 if ((unsigned long)s < PAGE_SIZE)
372 s = "<NULL>";
374 len = strnlen(s, precision);
376 if (!(flags & LEFT)) {
377 while (len < field_width--) {
378 if (str <= end)
379 *str = ' ';
380 ++str;
381 }
382 }
383 for (i = 0; i < len; ++i) {
384 if (str <= end)
385 *str = *s;
386 ++str; ++s;
387 }
388 while (len < field_width--) {
389 if (str <= end)
390 *str = ' ';
391 ++str;
392 }
393 continue;
395 case 'p':
396 if (field_width == -1) {
397 field_width = 2*sizeof(void *);
398 flags |= ZEROPAD;
399 }
400 str = number(str, end,
401 (unsigned long) va_arg(args, void *),
402 16, field_width, precision, flags);
403 continue;
406 case 'n':
407 if (qualifier == 'l') {
408 long * ip = va_arg(args, long *);
409 *ip = (str - buf);
410 } else if (qualifier == 'Z' || qualifier == 'z') {
411 size_t * ip = va_arg(args, size_t *);
412 *ip = (str - buf);
413 } else {
414 int * ip = va_arg(args, int *);
415 *ip = (str - buf);
416 }
417 continue;
419 case '%':
420 if (str <= end)
421 *str = '%';
422 ++str;
423 continue;
425 /* integer number formats - set up the flags and "break" */
426 case 'o':
427 base = 8;
428 break;
430 case 'X':
431 flags |= LARGE;
432 case 'x':
433 base = 16;
434 break;
436 case 'd':
437 case 'i':
438 flags |= SIGN;
439 case 'u':
440 break;
442 default:
443 if (str <= end)
444 *str = '%';
445 ++str;
446 if (*fmt) {
447 if (str <= end)
448 *str = *fmt;
449 ++str;
450 } else {
451 --fmt;
452 }
453 continue;
454 }
455 if (qualifier == 'L')
456 num = va_arg(args, long long);
457 else if (qualifier == 'l') {
458 num = va_arg(args, unsigned long);
459 if (flags & SIGN)
460 num = (signed long) num;
461 } else if (qualifier == 'Z' || qualifier == 'z') {
462 num = va_arg(args, size_t);
463 } else if (qualifier == 'h') {
464 num = (unsigned short) va_arg(args, int);
465 if (flags & SIGN)
466 num = (signed short) num;
467 } else {
468 num = va_arg(args, unsigned int);
469 if (flags & SIGN)
470 num = (signed int) num;
471 }
473 str = number(str, end, num, base,
474 field_width, precision, flags);
475 }
476 if (str <= end)
477 *str = '\0';
478 else if (size > 0)
479 /* don't write out a null byte if the buf size is zero */
480 *end = '\0';
481 /* the trailing null byte doesn't count towards the total
482 * ++str;
483 */
484 return str-buf;
485 }
487 EXPORT_SYMBOL(vsnprintf);
489 /**
490 * vscnprintf - Format a string and place it in a buffer
491 * @buf: The buffer to place the result into
492 * @size: The size of the buffer, including the trailing null space
493 * @fmt: The format string to use
494 * @args: Arguments for the format string
495 *
496 * The return value is the number of characters which have been written into
497 * the @buf not including the trailing '\0'. If @size is <= 0 the function
498 * returns 0.
499 *
500 * Call this function if you are already dealing with a va_list.
501 * You probably want scnprintf instead.
502 */
503 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
504 {
505 int i;
507 i=vsnprintf(buf,size,fmt,args);
508 return (i >= size) ? (size - 1) : i;
509 }
511 EXPORT_SYMBOL(vscnprintf);
513 /**
514 * vsscanf - Unformat a buffer into a list of arguments
515 * @buf: input buffer
516 * @fmt: format of buffer
517 * @args: arguments
518 */
519 int vsscanf(const char * buf, const char * fmt, va_list args)
520 {
521 const char *str = buf;
522 const char *next;
523 char digit;
524 int num = 0;
525 int qualifier;
526 int base;
527 int field_width;
528 int is_sign = 0;
530 while (*fmt && *str) {
531 /* skip any white space in format */
532 /* white space in format matchs any amount of
533 * white space, including none, in the input.
534 */
535 if (isspace(*fmt)) {
536 while (isspace(*fmt))
537 ++fmt;
538 while (isspace(*str))
539 ++str;
540 }
542 /* anything that is not a conversion must match exactly */
543 if (*fmt != '%' && *fmt) {
544 if (*fmt++ != *str++)
545 break;
546 continue;
547 }
549 if (!*fmt)
550 break;
551 ++fmt;
553 /* skip this conversion.
554 * advance both strings to next white space
555 */
556 if (*fmt == '*') {
557 while (!isspace(*fmt) && *fmt)
558 fmt++;
559 while (!isspace(*str) && *str)
560 str++;
561 continue;
562 }
564 /* get field width */
565 field_width = -1;
566 if (isdigit(*fmt))
567 field_width = skip_atoi(&fmt);
569 /* get conversion qualifier */
570 qualifier = -1;
571 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z'
572 || *fmt == 'z') {
573 qualifier = *fmt++;
574 if (unlikely(qualifier == *fmt)) {
575 if (qualifier == 'h') {
576 qualifier = 'H';
577 fmt++;
578 } else if (qualifier == 'l') {
579 qualifier = 'L';
580 fmt++;
581 }
582 }
583 }
584 base = 10;
585 is_sign = 0;
587 if (!*fmt || !*str)
588 break;
590 switch(*fmt++) {
591 case 'c': {
592 char *s = (char *) va_arg(args,char*);
593 if (field_width == -1)
594 field_width = 1;
595 do {
596 *s++ = *str++;
597 } while (--field_width > 0 && *str);
598 num++;
599 }
600 continue;
601 case 's': {
602 char *s = (char *) va_arg(args, char *);
603 if(field_width == -1)
604 field_width = INT_MAX;
605 /* first, skip leading white space in buffer */
606 while (isspace(*str))
607 str++;
609 /* now copy until next white space */
610 while (*str && !isspace(*str) && field_width--)
611 *s++ = *str++;
612 *s = '\0';
613 num++;
614 }
615 continue;
616 case 'n': {
617 /* return number of characters read so far */
618 int *i = (int *)va_arg(args,int*);
619 *i = str - buf;
620 }
621 continue;
622 case 'o':
623 base = 8;
624 break;
625 case 'x':
626 case 'X':
627 base = 16;
628 break;
629 case 'i':
630 base = 0;
631 case 'd':
632 is_sign = 1;
633 case 'u':
634 break;
635 case '%':
636 /* looking for '%' in str */
637 if (*str++ != '%')
638 return num;
639 continue;
640 default:
641 /* invalid format; stop here */
642 return num;
643 }
645 /* have some sort of integer conversion.
646 * first, skip white space in buffer.
647 */
648 while (isspace(*str))
649 str++;
651 digit = *str;
652 if (is_sign && digit == '-')
653 digit = *(str + 1);
655 if (!digit || (base == 16 && !isxdigit(digit))
656 || (base == 10 && !isdigit(digit))
657 || (base == 8 && (!isdigit(digit) || digit > '7'))
658 || (base == 0 && !isdigit(digit)))
659 break;
661 switch(qualifier) {
662 case 'H': /* that's 'hh' in format */
663 if (is_sign) {
664 signed char *s = (signed char *) va_arg(args,signed char *);
665 *s = (signed char) simple_strtol(str,&next,base);
666 } else {
667 unsigned char *s = (unsigned char *)
668 va_arg(args, unsigned char *);
669 *s = (unsigned char) simple_strtoul(str, &next, base);
670 }
671 break;
672 case 'h':
673 if (is_sign) {
674 short *s = (short *) va_arg(args,short *);
675 *s = (short) simple_strtol(str,&next,base);
676 } else {
677 unsigned short *s = (unsigned short *)
678 va_arg(args, unsigned short *);
679 *s = (unsigned short) simple_strtoul(str, &next, base);
680 }
681 break;
682 case 'l':
683 if (is_sign) {
684 long *l = (long *) va_arg(args,long *);
685 *l = simple_strtol(str,&next,base);
686 } else {
687 unsigned long *l = (unsigned long*)
688 va_arg(args,unsigned long*);
689 *l = simple_strtoul(str,&next,base);
690 }
691 break;
692 case 'L':
693 if (is_sign) {
694 long long *l = (long long*) va_arg(args,long long *);
695 *l = simple_strtoll(str,&next,base);
696 } else {
697 unsigned long long *l = (unsigned long long*)
698 va_arg(args,unsigned long long*);
699 *l = simple_strtoull(str,&next,base);
700 }
701 break;
702 case 'Z':
703 case 'z': {
704 size_t *s = (size_t*) va_arg(args,size_t*);
705 *s = (size_t) simple_strtoul(str,&next,base);
706 }
707 break;
708 default:
709 if (is_sign) {
710 int *i = (int *) va_arg(args, int*);
711 *i = (int) simple_strtol(str,&next,base);
712 } else {
713 unsigned int *i = (unsigned int*)
714 va_arg(args, unsigned int*);
715 *i = (unsigned int) simple_strtoul(str,&next,base);
716 }
717 break;
718 }
719 num++;
721 if (!next)
722 break;
723 str = next;
724 }
725 return num;
726 }
728 EXPORT_SYMBOL(vsscanf);
730 /**
731 * snprintf - Format a string and place it in a buffer
732 * @buf: The buffer to place the result into
733 * @size: The size of the buffer, including the trailing null space
734 * @fmt: The format string to use
735 * @...: Arguments for the format string
736 *
737 * The return value is the number of characters which would be
738 * generated for the given input, excluding the trailing null,
739 * as per ISO C99. If the return is greater than or equal to
740 * @size, the resulting string is truncated.
741 */
742 int snprintf(char * buf, size_t size, const char *fmt, ...)
743 {
744 va_list args;
745 int i;
747 va_start(args, fmt);
748 i=vsnprintf(buf,size,fmt,args);
749 va_end(args);
750 return i;
751 }
753 EXPORT_SYMBOL(snprintf);
755 /**
756 * scnprintf - Format a string and place it in a buffer
757 * @buf: The buffer to place the result into
758 * @size: The size of the buffer, including the trailing null space
759 * @fmt: The format string to use
760 * @...: Arguments for the format string
761 *
762 * The return value is the number of characters written into @buf not including
763 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
764 * greater than or equal to @size, the resulting string is truncated.
765 */
767 int scnprintf(char * buf, size_t size, const char *fmt, ...)
768 {
769 va_list args;
770 int i;
772 va_start(args, fmt);
773 i = vsnprintf(buf, size, fmt, args);
774 va_end(args);
775 return (i >= size) ? (size - 1) : i;
776 }
777 EXPORT_SYMBOL(scnprintf);
779 /**
780 * sscanf - Unformat a buffer into a list of arguments
781 * @buf: input buffer
782 * @fmt: formatting of buffer
783 * @...: resulting arguments
784 */
785 int sscanf(const char * buf, const char * fmt, ...)
786 {
787 va_list args;
788 int i;
790 va_start(args,fmt);
791 i = vsscanf(buf,fmt,args);
792 va_end(args);
793 return i;
794 }
796 EXPORT_SYMBOL(sscanf);
798 /*
799 * Local variables:
800 * mode: C
801 * c-set-style: "BSD"
802 * c-basic-offset: 4
803 * tab-width: 4
804 * indent-tabs-mode: nil
805 * End:
806 */