vsprintf.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/lib/vsprintf.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  7. /*
  8.  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  9.  */
  10. /* 
  11.  * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
  12.  * - changed to provide snprintf and vsnprintf functions
  13.  */
  14. #include <stdarg.h>
  15. #include <linux/types.h>
  16. #include <linux/string.h>
  17. #include <linux/ctype.h>
  18. #include <linux/kernel.h>
  19. #include <asm/div64.h>
  20. /**
  21.  * simple_strtoul - convert a string to an unsigned long
  22.  * @cp: The start of the string
  23.  * @endp: A pointer to the end of the parsed string will be placed here
  24.  * @base: The number base to use
  25.  */
  26. unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  27. {
  28. unsigned long result = 0,value;
  29. if (!base) {
  30. base = 10;
  31. if (*cp == '0') {
  32. base = 8;
  33. cp++;
  34. if ((*cp == 'x') && isxdigit(cp[1])) {
  35. cp++;
  36. base = 16;
  37. }
  38. }
  39. }
  40. while (isxdigit(*cp) &&
  41.        (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
  42. result = result*base + value;
  43. cp++;
  44. }
  45. if (endp)
  46. *endp = (char *)cp;
  47. return result;
  48. }
  49. /**
  50.  * simple_strtol - convert a string to a signed long
  51.  * @cp: The start of the string
  52.  * @endp: A pointer to the end of the parsed string will be placed here
  53.  * @base: The number base to use
  54.  */
  55. long simple_strtol(const char *cp,char **endp,unsigned int base)
  56. {
  57. if(*cp=='-')
  58. return -simple_strtoul(cp+1,endp,base);
  59. return simple_strtoul(cp,endp,base);
  60. }
  61. /**
  62.  * simple_strtoull - convert a string to an unsigned long 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. unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
  68. {
  69. unsigned long long result = 0,value;
  70. if (!base) {
  71. base = 10;
  72. if (*cp == '0') {
  73. base = 8;
  74. cp++;
  75. if ((*cp == 'x') && isxdigit(cp[1])) {
  76. cp++;
  77. base = 16;
  78. }
  79. }
  80. }
  81. while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  82.     ? toupper(*cp) : *cp)-'A'+10) < base) {
  83. result = result*base + value;
  84. cp++;
  85. }
  86. if (endp)
  87. *endp = (char *)cp;
  88. return result;
  89. }
  90. /**
  91.  * simple_strtoll - convert a string to a signed long long
  92.  * @cp: The start of the string
  93.  * @endp: A pointer to the end of the parsed string will be placed here
  94.  * @base: The number base to use
  95.  */
  96. long long simple_strtoll(const char *cp,char **endp,unsigned int base)
  97. {
  98. if(*cp=='-')
  99. return -simple_strtoull(cp+1,endp,base);
  100. return simple_strtoull(cp,endp,base);
  101. }
  102. static int skip_atoi(const char **s)
  103. {
  104. int i=0;
  105. while (isdigit(**s))
  106. i = i*10 + *((*s)++) - '0';
  107. return i;
  108. }
  109. #define ZEROPAD 1 /* pad with zero */
  110. #define SIGN 2 /* unsigned/signed long */
  111. #define PLUS 4 /* show plus */
  112. #define SPACE 8 /* space if plus */
  113. #define LEFT 16 /* left justified */
  114. #define SPECIAL 32 /* 0x */
  115. #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
  116. static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
  117. {
  118. char c,sign,tmp[66];
  119. const char *digits;
  120. const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  121. const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  122. int i;
  123. digits = (type & LARGE) ? large_digits : small_digits;
  124. if (type & LEFT)
  125. type &= ~ZEROPAD;
  126. if (base < 2 || base > 36)
  127. return 0;
  128. c = (type & ZEROPAD) ? '0' : ' ';
  129. sign = 0;
  130. if (type & SIGN) {
  131. if (num < 0) {
  132. sign = '-';
  133. num = -num;
  134. size--;
  135. } else if (type & PLUS) {
  136. sign = '+';
  137. size--;
  138. } else if (type & SPACE) {
  139. sign = ' ';
  140. size--;
  141. }
  142. }
  143. if (type & SPECIAL) {
  144. if (base == 16)
  145. size -= 2;
  146. else if (base == 8)
  147. size--;
  148. }
  149. i = 0;
  150. if (num == 0)
  151. tmp[i++]='0';
  152. else while (num != 0)
  153. tmp[i++] = digits[do_div(num,base)];
  154. if (i > precision)
  155. precision = i;
  156. size -= precision;
  157. if (!(type&(ZEROPAD+LEFT))) {
  158. while(size-->0) {
  159. if (buf <= end)
  160. *buf = ' ';
  161. ++buf;
  162. }
  163. }
  164. if (sign) {
  165. if (buf <= end)
  166. *buf = sign;
  167. ++buf;
  168. }
  169. if (type & SPECIAL) {
  170. if (base==8) {
  171. if (buf <= end)
  172. *buf = '0';
  173. ++buf;
  174. } else if (base==16) {
  175. if (buf <= end)
  176. *buf = '0';
  177. ++buf;
  178. if (buf <= end)
  179. *buf = digits[33];
  180. ++buf;
  181. }
  182. }
  183. if (!(type & LEFT)) {
  184. while (size-- > 0) {
  185. if (buf <= end)
  186. *buf = c;
  187. ++buf;
  188. }
  189. }
  190. while (i < precision--) {
  191. if (buf <= end)
  192. *buf = '0';
  193. ++buf;
  194. }
  195. while (i-- > 0) {
  196. if (buf <= end)
  197. *buf = tmp[i];
  198. ++buf;
  199. }
  200. while (size-- > 0) {
  201. if (buf <= end)
  202. *buf = ' ';
  203. ++buf;
  204. }
  205. return buf;
  206. }
  207. /**
  208. * vsnprintf - Format a string and place it in a buffer
  209. * @buf: The buffer to place the result into
  210. * @size: The size of the buffer, including the trailing null space
  211. * @fmt: The format string to use
  212. * @args: Arguments for the format string
  213. *
  214. * Call this function if you are already dealing with a va_list.
  215. * You probably want snprintf instead.
  216.  */
  217. int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
  218. {
  219. int len;
  220. unsigned long long num;
  221. int i, base;
  222. char *str, *end, c;
  223. const char *s;
  224. int flags; /* flags to number() */
  225. int field_width; /* width of output field */
  226. int precision; /* min. # of digits for integers; max
  227.    number of chars for from string */
  228. int qualifier; /* 'h', 'l', or 'L' for integer fields */
  229. /* 'z' support added 23/7/1999 S.H.    */
  230. /* 'z' changed to 'Z' --davidm 1/25/99 */
  231. str = buf;
  232. end = buf + size - 1;
  233. if (end < buf - 1) {
  234. end = ((void *) -1);
  235. size = end - buf + 1;
  236. }
  237. for (; *fmt ; ++fmt) {
  238. if (*fmt != '%') {
  239. if (str <= end)
  240. *str = *fmt;
  241. ++str;
  242. continue;
  243. }
  244. /* process flags */
  245. flags = 0;
  246. repeat:
  247. ++fmt; /* this also skips first '%' */
  248. switch (*fmt) {
  249. case '-': flags |= LEFT; goto repeat;
  250. case '+': flags |= PLUS; goto repeat;
  251. case ' ': flags |= SPACE; goto repeat;
  252. case '#': flags |= SPECIAL; goto repeat;
  253. case '0': flags |= ZEROPAD; goto repeat;
  254. }
  255. /* get field width */
  256. field_width = -1;
  257. if (isdigit(*fmt))
  258. field_width = skip_atoi(&fmt);
  259. else if (*fmt == '*') {
  260. ++fmt;
  261. /* it's the next argument */
  262. field_width = va_arg(args, int);
  263. if (field_width < 0) {
  264. field_width = -field_width;
  265. flags |= LEFT;
  266. }
  267. }
  268. /* get the precision */
  269. precision = -1;
  270. if (*fmt == '.') {
  271. ++fmt;
  272. if (isdigit(*fmt))
  273. precision = skip_atoi(&fmt);
  274. else if (*fmt == '*') {
  275. ++fmt;
  276. /* it's the next argument */
  277. precision = va_arg(args, int);
  278. }
  279. if (precision < 0)
  280. precision = 0;
  281. }
  282. /* get the conversion qualifier */
  283. qualifier = -1;
  284. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
  285. qualifier = *fmt;
  286. ++fmt;
  287. if (qualifier == 'l' && *fmt == 'l') {
  288. qualifier = 'L';
  289. ++fmt;
  290. }
  291. }
  292. /* default base */
  293. base = 10;
  294. switch (*fmt) {
  295. case 'c':
  296. if (!(flags & LEFT)) {
  297. while (--field_width > 0) {
  298. if (str <= end)
  299. *str = ' ';
  300. ++str;
  301. }
  302. }
  303. c = (unsigned char) va_arg(args, int);
  304. if (str <= end)
  305. *str = c;
  306. ++str;
  307. while (--field_width > 0) {
  308. if (str <= end)
  309. *str = ' ';
  310. ++str;
  311. }
  312. continue;
  313. case 's':
  314. s = va_arg(args, char *);
  315. if (!s)
  316. s = "<NULL>";
  317. len = strnlen(s, precision);
  318. if (!(flags & LEFT)) {
  319. while (len < field_width--) {
  320. if (str <= end)
  321. *str = ' ';
  322. ++str;
  323. }
  324. }
  325. for (i = 0; i < len; ++i) {
  326. if (str <= end)
  327. *str = *s;
  328. ++str; ++s;
  329. }
  330. while (len < field_width--) {
  331. if (str <= end)
  332. *str = ' ';
  333. ++str;
  334. }
  335. continue;
  336. case 'p':
  337. if (field_width == -1) {
  338. field_width = 2*sizeof(void *);
  339. flags |= ZEROPAD;
  340. }
  341. str = number(str, end,
  342. (unsigned long) va_arg(args, void *),
  343. 16, field_width, precision, flags);
  344. continue;
  345. case 'n':
  346. /* FIXME:
  347. * What does C99 say about the overflow case here? */
  348. if (qualifier == 'l') {
  349. long * ip = va_arg(args, long *);
  350. *ip = (str - buf);
  351. } else if (qualifier == 'Z') {
  352. size_t * ip = va_arg(args, size_t *);
  353. *ip = (str - buf);
  354. } else {
  355. int * ip = va_arg(args, int *);
  356. *ip = (str - buf);
  357. }
  358. continue;
  359. case '%':
  360. if (str <= end)
  361. *str = '%';
  362. ++str;
  363. continue;
  364. /* integer number formats - set up the flags and "break" */
  365. case 'o':
  366. base = 8;
  367. break;
  368. case 'X':
  369. flags |= LARGE;
  370. case 'x':
  371. base = 16;
  372. break;
  373. case 'd':
  374. case 'i':
  375. flags |= SIGN;
  376. case 'u':
  377. break;
  378. default:
  379. if (str <= end)
  380. *str = '%';
  381. ++str;
  382. if (*fmt) {
  383. if (str <= end)
  384. *str = *fmt;
  385. ++str;
  386. } else {
  387. --fmt;
  388. }
  389. continue;
  390. }
  391. if (qualifier == 'L')
  392. num = va_arg(args, long long);
  393. else if (qualifier == 'l') {
  394. num = va_arg(args, unsigned long);
  395. if (flags & SIGN)
  396. num = (signed long) num;
  397. } else if (qualifier == 'Z') {
  398. num = va_arg(args, size_t);
  399. } else if (qualifier == 'h') {
  400. num = (unsigned short) va_arg(args, int);
  401. if (flags & SIGN)
  402. num = (signed short) num;
  403. } else {
  404. num = va_arg(args, unsigned int);
  405. if (flags & SIGN)
  406. num = (signed int) num;
  407. }
  408. str = number(str, end, num, base,
  409. field_width, precision, flags);
  410. }
  411. if (str <= end)
  412. *str = '';
  413. else if (size > 0)
  414. /* don't write out a null byte if the buf size is zero */
  415. *end = '';
  416. /* the trailing null byte doesn't count towards the total
  417. * ++str;
  418. */
  419. return str-buf;
  420. }
  421. /**
  422.  * snprintf - Format a string and place it in a buffer
  423.  * @buf: The buffer to place the result into
  424.  * @size: The size of the buffer, including the trailing null space
  425.  * @fmt: The format string to use
  426.  * @...: Arguments for the format string
  427.  */
  428. int snprintf(char * buf, size_t size, const char *fmt, ...)
  429. {
  430. va_list args;
  431. int i;
  432. va_start(args, fmt);
  433. i=vsnprintf(buf,size,fmt,args);
  434. va_end(args);
  435. return i;
  436. }
  437. /**
  438.  * vsprintf - Format a string and place it in a buffer
  439.  * @buf: The buffer to place the result into
  440.  * @fmt: The format string to use
  441.  * @args: Arguments for the format string
  442.  *
  443.  * Call this function if you are already dealing with a va_list.
  444.  * You probably want sprintf instead.
  445.  */
  446. int vsprintf(char *buf, const char *fmt, va_list args)
  447. {
  448. return vsnprintf(buf, 0xFFFFFFFFUL, fmt, args);
  449. }
  450. /**
  451.  * sprintf - Format a string and place it in a buffer
  452.  * @buf: The buffer to place the result into
  453.  * @fmt: The format string to use
  454.  * @...: Arguments for the format string
  455.  */
  456. int sprintf(char * buf, const char *fmt, ...)
  457. {
  458. va_list args;
  459. int i;
  460. va_start(args, fmt);
  461. i=vsprintf(buf,fmt,args);
  462. va_end(args);
  463. return i;
  464. }
  465. /**
  466.  * vsscanf - Unformat a buffer into a list of arguments
  467.  * @buf: input buffer
  468.  * @fmt: format of buffer
  469.  * @args: arguments
  470.  */
  471. int vsscanf(const char * buf, const char * fmt, va_list args)
  472. {
  473. const char *str = buf;
  474. char *next;
  475. int num = 0;
  476. int qualifier;
  477. int base;
  478. int field_width = -1;
  479. int is_sign = 0;
  480. while(*fmt && *str) {
  481. /* skip any white space in format */
  482. /* white space in format matchs any amount of
  483.  * white space, including none, in the input.
  484.  */
  485. if (isspace(*fmt)) {
  486. while (isspace(*fmt))
  487. ++fmt;
  488. while (isspace(*str))
  489. ++str;
  490. }
  491. /* anything that is not a conversion must match exactly */
  492. if (*fmt != '%' && *fmt) {
  493. if (*fmt++ != *str++)
  494. break;
  495. continue;
  496. }
  497. if (!*fmt)
  498. break;
  499. ++fmt;
  500. /* skip this conversion.
  501.  * advance both strings to next white space
  502.  */
  503. if (*fmt == '*') {
  504. while (!isspace(*fmt) && *fmt)
  505. fmt++;
  506. while (!isspace(*str) && *str)
  507. str++;
  508. continue;
  509. }
  510. /* get field width */
  511. if (isdigit(*fmt))
  512. field_width = skip_atoi(&fmt);
  513. /* get conversion qualifier */
  514. qualifier = -1;
  515. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') {
  516. qualifier = *fmt;
  517. fmt++;
  518. }
  519. base = 10;
  520. is_sign = 0;
  521. if (!*fmt || !*str)
  522. break;
  523. switch(*fmt++) {
  524. case 'c':
  525. {
  526. char *s = (char *) va_arg(args,char*);
  527. if (field_width == -1)
  528. field_width = 1;
  529. do {
  530. *s++ = *str++;
  531. } while(field_width-- > 0 && *str);
  532. num++;
  533. }
  534. continue;
  535. case 's':
  536. {
  537. char *s = (char *) va_arg(args, char *);
  538. if(field_width == -1)
  539. field_width = INT_MAX;
  540. /* first, skip leading white space in buffer */
  541. while (isspace(*str))
  542. str++;
  543. /* now copy until next white space */
  544. while (*str && !isspace(*str) && field_width--) {
  545. *s++ = *str++;
  546. }
  547. *s = '';
  548. num++;
  549. }
  550. continue;
  551. case 'n':
  552. /* return number of characters read so far */
  553. {
  554. int *i = (int *)va_arg(args,int*);
  555. *i = str - buf;
  556. }
  557. continue;
  558. case 'o':
  559. base = 8;
  560. break;
  561. case 'x':
  562. case 'X':
  563. base = 16;
  564. break;
  565. case 'd':
  566. case 'i':
  567. is_sign = 1;
  568. case 'u':
  569. break;
  570. case '%':
  571. /* looking for '%' in str */
  572. if (*str++ != '%') 
  573. return num;
  574. continue;
  575. default:
  576. /* invalid format; stop here */
  577. return num;
  578. }
  579. /* have some sort of integer conversion.
  580.  * first, skip white space in buffer.
  581.  */
  582. while (isspace(*str))
  583. str++;
  584. if (!*str || !isdigit(*str))
  585. break;
  586. switch(qualifier) {
  587. case 'h':
  588. if (is_sign) {
  589. short *s = (short *) va_arg(args,short *);
  590. *s = (short) simple_strtol(str,&next,base);
  591. } else {
  592. unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
  593. *s = (unsigned short) simple_strtoul(str, &next, base);
  594. }
  595. break;
  596. case 'l':
  597. if (is_sign) {
  598. long *l = (long *) va_arg(args,long *);
  599. *l = simple_strtol(str,&next,base);
  600. } else {
  601. unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
  602. *l = simple_strtoul(str,&next,base);
  603. }
  604. break;
  605. case 'L':
  606. if (is_sign) {
  607. long long *l = (long long*) va_arg(args,long long *);
  608. *l = simple_strtoll(str,&next,base);
  609. } else {
  610. unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
  611. *l = simple_strtoull(str,&next,base);
  612. }
  613. break;
  614. case 'Z':
  615. {
  616. size_t *s = (size_t*) va_arg(args,size_t*);
  617. *s = (size_t) simple_strtoul(str,&next,base);
  618. }
  619. break;
  620. default:
  621. if (is_sign) {
  622. int *i = (int *) va_arg(args, int*);
  623. *i = (int) simple_strtol(str,&next,base);
  624. } else {
  625. unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
  626. *i = (unsigned int) simple_strtoul(str,&next,base);
  627. }
  628. break;
  629. }
  630. num++;
  631. if (!next)
  632. break;
  633. str = next;
  634. }
  635. return num;
  636. }
  637. /**
  638.  * sscanf - Unformat a buffer into a list of arguments
  639.  * @buf: input buffer
  640.  * @fmt: formatting of buffer
  641.  * @...: resulting arguments
  642.  */
  643. int sscanf(const char * buf, const char * fmt, ...)
  644. {
  645. va_list args;
  646. int i;
  647. va_start(args,fmt);
  648. i = vsscanf(buf,fmt,args);
  649. va_end(args);
  650. return i;
  651. }