debuggers.hg

annotate xen/common/vsprintf.c @ 22848:6341fe0f4e5a

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