Advertisement
Guest User

Untitled

a guest
Aug 2nd, 2015
374
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.79 KB | None | 0 0
  1. //#ifdef DEBUG
  2.  
  3. /*
  4. * Copyright (c) 1995 Patrick Powell.
  5. *
  6. * This code is based on code written by Patrick Powell <papowell@astart.com>.
  7. * It may be used for any purpose as long as this notice remains intact on all
  8. * source code distributions.
  9. */
  10.  
  11. /*
  12. * Copyright (c) 2008 Holger Weiss.
  13. *
  14. * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
  15. * My changes to the code may freely be used, modified and/or redistributed for
  16. * any purpose. It would be nice if additions and fixes to this file (including
  17. * trivial code cleanups) would be sent back in order to let me include them in
  18. * the version available at <http://www.jhweiss.de/software/snprintf.html>.
  19. * However, this is not a requirement for using or redistributing (possibly
  20. * modified) versions of this file, nor is leaving this notice intact mandatory.
  21. */
  22.  
  23. /*
  24. * History
  25. *
  26. * 2009-03-05 Hector Martin <hector@marcansoft.com>
  27. *
  28. * Hacked up and removed a lot of stuff including floating-point support,
  29. * a bunch of ifs and defines, locales, and tests
  30. *
  31. * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
  32. *
  33. * Fixed the detection of infinite floating point values on IRIX (and
  34. * possibly other systems) and applied another few minor cleanups.
  35. *
  36. * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
  37. *
  38. * Added a lot of new features, fixed many bugs, and incorporated various
  39. * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
  40. * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
  41. * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
  42. * projects. The additions include: support the "e", "E", "g", "G", and
  43. * "F" conversion specifiers (and use conversion style "f" or "F" for the
  44. * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
  45. * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
  46. * "'" flag; use localeconv(3) (if available) to get both the current
  47. * locale's decimal point character and the separator between groups of
  48. * digits; fix the handling of various corner cases of field width and
  49. * precision specifications; fix various floating point conversion bugs;
  50. * handle infinite and NaN floating point values; don't attempt to write to
  51. * the output buffer (which may be NULL) if a size of zero was specified;
  52. * check for integer overflow of the field width, precision, and return
  53. * values and during the floating point conversion; use the OUTCHAR() macro
  54. * instead of a function for better performance; provide asprintf(3) and
  55. * vasprintf(3) functions; add new test cases. The replacement functions
  56. * have been renamed to use an "rpl_" prefix, the function calls in the
  57. * main project (and in this file) must be redefined accordingly for each
  58. * replacement function which is needed (by using Autoconf or other means).
  59. * Various other minor improvements have been applied and the coding style
  60. * was cleaned up for consistency.
  61. *
  62. * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
  63. *
  64. * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
  65. * of characters that would have been written to a sufficiently sized
  66. * buffer (excluding the '\0'). The original code simply returned the
  67. * length of the resulting output string, so that's been fixed.
  68. *
  69. * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
  70. *
  71. * The original code assumed that both snprintf(3) and vsnprintf(3) were
  72. * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
  73. * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
  74. *
  75. * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
  76. *
  77. * The PGP code was using unsigned hexadecimal formats. Unfortunately,
  78. * unsigned formats simply didn't work.
  79. *
  80. * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
  81. *
  82. * Ok, added some minimal floating point support, which means this probably
  83. * requires libm on most operating systems. Don't yet support the exponent
  84. * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
  85. * wasn't being exercised in ways which showed it, so that's been fixed.
  86. * Also, formatted the code to Mutt conventions, and removed dead code left
  87. * over from the original. Also, there is now a builtin-test, run with:
  88. * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
  89. *
  90. * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
  91. *
  92. * This was ugly. It is still ugly. I opted out of floating point
  93. * numbers, but the formatter understands just about everything from the
  94. * normal C string format, at least as far as I can tell from the Solaris
  95. * 2.5 printf(3S) man page.
  96. */
  97.  
  98. #include <cell/cell_fs.h>
  99.  
  100. #include <stdlib.h>
  101. #include <limits.h>
  102. #include <stdarg.h>
  103. //#include "printf.h"
  104.  
  105. #define HAVE_UNSIGNED_LONG_LONG_INT
  106. #define HAVE_STDINT_H
  107. #define HAVE_INTTYPES_H
  108. #define HAVE_STDDEF_H
  109. #define HAVE_LONG_LONG_INT
  110.  
  111. #define VA_START(ap, last) va_start(ap, last)
  112. #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
  113.  
  114. #ifdef HAVE_INTTYPES_H
  115. #include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
  116. #endif /* HAVE_INTTYPES_H */
  117.  
  118. #ifdef HAVE_STDDEF_H
  119. #include <stddef.h> /* For ptrdiff_t. */
  120. #endif /* HAVE_STDDEF_H */
  121.  
  122. #ifdef HAVE_STDINT_H
  123. #include <stdint.h> /* For intmax_t. */
  124. #endif /* HAVE_STDINT_H */
  125.  
  126. /* Support for unsigned long long int. We may also need ULLONG_MAX. */
  127. #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
  128. #ifdef UINT_MAX
  129. #define ULONG_MAX UINT_MAX
  130. #else
  131. #define ULONG_MAX INT_MAX
  132. #endif /* defined(UINT_MAX) */
  133. #endif /* !defined(ULONG_MAX) */
  134. #ifdef ULLONG
  135. #undef ULLONG
  136. #endif /* defined(ULLONG) */
  137. #ifdef HAVE_UNSIGNED_LONG_LONG_INT
  138. #define ULLONG unsigned long long int
  139. #ifndef ULLONG_MAX
  140. #define ULLONG_MAX ULONG_MAX
  141. #endif /* !defined(ULLONG_MAX) */
  142. #else
  143. #define ULLONG unsigned long int
  144. #ifdef ULLONG_MAX
  145. #undef ULLONG_MAX
  146. #endif /* defined(ULLONG_MAX) */
  147. #define ULLONG_MAX ULONG_MAX
  148. #endif /* HAVE_LONG_LONG_INT */
  149.  
  150. /* Support for uintmax_t. We also need UINTMAX_MAX. */
  151. #ifdef UINTMAX_T
  152. #undef UINTMAX_T
  153. #endif /* defined(UINTMAX_T) */
  154. #if HAVE_UINTMAX_T || defined(uintmax_t)
  155. #define UINTMAX_T uintmax_t
  156. #ifndef UINTMAX_MAX
  157. #define UINTMAX_MAX ULLONG_MAX
  158. #endif /* !defined(UINTMAX_MAX) */
  159. #else
  160. #define UINTMAX_T ULLONG
  161. #ifdef UINTMAX_MAX
  162. #undef UINTMAX_MAX
  163. #endif /* defined(UINTMAX_MAX) */
  164. #define UINTMAX_MAX ULLONG_MAX
  165. #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
  166.  
  167. /* Support for long long int. */
  168. #ifndef LLONG
  169. #ifdef HAVE_LONG_LONG_INT
  170. #define LLONG long long int
  171. #else
  172. #define LLONG long int
  173. #endif /* HAVE_LONG_LONG_INT */
  174. #endif /* !defined(LLONG) */
  175.  
  176. /* Support for intmax_t. */
  177. #ifndef INTMAX_T
  178. #if HAVE_INTMAX_T || defined(intmax_t)
  179. #define INTMAX_T intmax_t
  180. #else
  181. #define INTMAX_T LLONG
  182. #endif /* HAVE_INTMAX_T || defined(intmax_t) */
  183. #endif /* !defined(INTMAX_T) */
  184.  
  185. /* Support for uintptr_t. */
  186. #ifndef UINTPTR_T
  187. #if HAVE_UINTPTR_T || defined(uintptr_t)
  188. #define UINTPTR_T uintptr_t
  189. #else
  190. #define UINTPTR_T unsigned long int
  191. #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
  192. #endif /* !defined(UINTPTR_T) */
  193.  
  194. /* Support for ptrdiff_t. */
  195. #ifndef PTRDIFF_T
  196. #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
  197. #define PTRDIFF_T ptrdiff_t
  198. #else
  199. #define PTRDIFF_T long int
  200. #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
  201. #endif /* !defined(PTRDIFF_T) */
  202.  
  203. /*
  204. * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
  205. * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
  206. * unsigned type if necessary. This should work just fine in practice.
  207. */
  208. #ifndef UPTRDIFF_T
  209. #define UPTRDIFF_T PTRDIFF_T
  210. #endif /* !defined(UPTRDIFF_T) */
  211.  
  212. /*
  213. * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
  214. * However, we'll simply use size_t and convert it to a signed type if
  215. * necessary. This should work just fine in practice.
  216. */
  217. #ifndef SSIZE_T
  218. #define SSIZE_T size_t
  219. #endif /* !defined(SSIZE_T) */
  220.  
  221.  
  222. /*
  223. * Buffer size to hold the octal string representation of UINT128_MAX without
  224. * nul-termination ("3777777777777777777777777777777777777777777").
  225. */
  226. #ifdef MAX_CONVERT_LENGTH
  227. #undef MAX_CONVERT_LENGTH
  228. #endif /* defined(MAX_CONVERT_LENGTH) */
  229. #define MAX_CONVERT_LENGTH 43
  230.  
  231. /* Format read states. */
  232. #define PRINT_S_DEFAULT 0
  233. #define PRINT_S_FLAGS 1
  234. #define PRINT_S_WIDTH 2
  235. #define PRINT_S_DOT 3
  236. #define PRINT_S_PRECISION 4
  237. #define PRINT_S_MOD 5
  238. #define PRINT_S_CONV 6
  239.  
  240. /* Format flags. */
  241. #define PRINT_F_MINUS (1 << 0)
  242. #define PRINT_F_PLUS (1 << 1)
  243. #define PRINT_F_SPACE (1 << 2)
  244. #define PRINT_F_NUM (1 << 3)
  245. #define PRINT_F_ZERO (1 << 4)
  246. #define PRINT_F_QUOTE (1 << 5)
  247. #define PRINT_F_UP (1 << 6)
  248. #define PRINT_F_UNSIGNED (1 << 7)
  249. #define PRINT_F_TYPE_G (1 << 8)
  250. #define PRINT_F_TYPE_E (1 << 9)
  251.  
  252. /* Conversion flags. */
  253. #define PRINT_C_CHAR 1
  254. #define PRINT_C_SHORT 2
  255. #define PRINT_C_LONG 3
  256. #define PRINT_C_LLONG 4
  257. //#define PRINT_C_LDOUBLE 5
  258. #define PRINT_C_SIZE 6
  259. #define PRINT_C_PTRDIFF 7
  260. #define PRINT_C_INTMAX 8
  261.  
  262. #ifndef MAX
  263. #define MAX(x, y) ((x >= y) ? x : y)
  264. #endif /* !defined(MAX) */
  265. #ifndef CHARTOINT
  266. #define CHARTOINT(ch) (ch - '0')
  267. #endif /* !defined(CHARTOINT) */
  268. #ifndef ISDIGIT
  269. #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
  270. #endif /* !defined(ISDIGIT) */
  271.  
  272. #define OUTCHAR(str, len, size, ch) \
  273. do { \
  274. if (len + 1 < size) \
  275. str[len] = ch; \
  276. (len)++; \
  277. } while (/* CONSTCOND */ 0)
  278.  
  279.  
  280. #include <string.h>
  281.  
  282. namespace std
  283. {
  284.  
  285.  
  286. static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
  287. static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
  288. static void printsep(char *, size_t *, size_t);
  289. static int getnumsep(int);
  290. static int convert(UINTMAX_T, char *, size_t, int, int);
  291.  
  292.  
  293. int vsnprintf(char *str, size_t size, const char *format, va_list args)
  294. {
  295. if (!format)
  296. return 0;
  297.  
  298. INTMAX_T value;
  299. unsigned char cvalue;
  300. const char *strvalue;
  301. INTMAX_T *intmaxptr;
  302. PTRDIFF_T *ptrdiffptr;
  303. SSIZE_T *sizeptr;
  304. LLONG *llongptr;
  305. long int *longptr;
  306. int *intptr;
  307. short int *shortptr;
  308. signed char *charptr;
  309. size_t len = 0;
  310. int overflow = 0;
  311. int base = 0;
  312. int cflags = 0;
  313. int flags = 0;
  314. int width = 0;
  315. int precision = -1;
  316. int state = PRINT_S_DEFAULT;
  317. char ch = *format++;
  318.  
  319. /*
  320. * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
  321. * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
  322. * even if a size larger than zero was specified. At least NetBSD's
  323. * snprintf(3) does the same, as well as other versions of this file.
  324. * (Though some of these versions will write to a non-NULL buffer even
  325. * if a size of zero was specified, which violates the standard.)
  326. */
  327. if (str == NULL && size != 0)
  328. size = 0;
  329.  
  330. while (ch != '\0')
  331. switch (state) {
  332. case PRINT_S_DEFAULT:
  333. if (ch == '%')
  334. state = PRINT_S_FLAGS;
  335. else
  336. OUTCHAR(str, len, size, ch);
  337. ch = *format++;
  338. break;
  339. case PRINT_S_FLAGS:
  340. switch (ch) {
  341. case '-':
  342. flags |= PRINT_F_MINUS;
  343. ch = *format++;
  344. break;
  345. case '+':
  346. flags |= PRINT_F_PLUS;
  347. ch = *format++;
  348. break;
  349. case ' ':
  350. flags |= PRINT_F_SPACE;
  351. ch = *format++;
  352. break;
  353. case '#':
  354. flags |= PRINT_F_NUM;
  355. ch = *format++;
  356. break;
  357. case '0':
  358. flags |= PRINT_F_ZERO;
  359. ch = *format++;
  360. break;
  361. case '\'': /* SUSv2 flag (not in C99). */
  362. flags |= PRINT_F_QUOTE;
  363. ch = *format++;
  364. break;
  365. default:
  366. state = PRINT_S_WIDTH;
  367. break;
  368. }
  369. break;
  370. case PRINT_S_WIDTH:
  371. if (ISDIGIT(ch)) {
  372. ch = CHARTOINT(ch);
  373. if (width > (INT_MAX - ch) / 10) {
  374. overflow = 1;
  375. goto out;
  376. }
  377. width = 10 * width + ch;
  378. ch = *format++;
  379. }
  380. else if (ch == '*') {
  381. /*
  382. * C99 says: "A negative field width argument is
  383. * taken as a `-' flag followed by a positive
  384. * field width." (7.19.6.1, 5)
  385. */
  386. if ((width = va_arg(args, int)) < 0) {
  387. flags |= PRINT_F_MINUS;
  388. width = -width;
  389. }
  390. ch = *format++;
  391. state = PRINT_S_DOT;
  392. }
  393. else
  394. state = PRINT_S_DOT;
  395. break;
  396. case PRINT_S_DOT:
  397. if (ch == '.') {
  398. state = PRINT_S_PRECISION;
  399. ch = *format++;
  400. }
  401. else
  402. state = PRINT_S_MOD;
  403. break;
  404. case PRINT_S_PRECISION:
  405. if (precision == -1)
  406. precision = 0;
  407. if (ISDIGIT(ch)) {
  408. ch = CHARTOINT(ch);
  409. if (precision > (INT_MAX - ch) / 10) {
  410. overflow = 1;
  411. goto out;
  412. }
  413. precision = 10 * precision + ch;
  414. ch = *format++;
  415. }
  416. else if (ch == '*') {
  417. /*
  418. * C99 says: "A negative precision argument is
  419. * taken as if the precision were omitted."
  420. * (7.19.6.1, 5)
  421. */
  422. if ((precision = va_arg(args, int)) < 0)
  423. precision = -1;
  424. ch = *format++;
  425. state = PRINT_S_MOD;
  426. }
  427. else
  428. state = PRINT_S_MOD;
  429. break;
  430. case PRINT_S_MOD:
  431. switch (ch) {
  432. case 'h':
  433. ch = *format++;
  434. if (ch == 'h') { /* It's a char. */
  435. ch = *format++;
  436. cflags = PRINT_C_CHAR;
  437. }
  438. else
  439. cflags = PRINT_C_SHORT;
  440. break;
  441. case 'l':
  442. ch = *format++;
  443. if (ch == 'l') { /* It's a long long. */
  444. ch = *format++;
  445. cflags = PRINT_C_LLONG;
  446. }
  447. else
  448. cflags = PRINT_C_LONG;
  449. break;
  450. case 'j':
  451. cflags = PRINT_C_INTMAX;
  452. ch = *format++;
  453. break;
  454. case 't':
  455. cflags = PRINT_C_PTRDIFF;
  456. ch = *format++;
  457. break;
  458. case 'z':
  459. cflags = PRINT_C_SIZE;
  460. ch = *format++;
  461. break;
  462. }
  463. state = PRINT_S_CONV;
  464. break;
  465. case PRINT_S_CONV:
  466. switch (ch) {
  467. case 'd':
  468. /* FALLTHROUGH */
  469. case 'i':
  470. switch (cflags) {
  471. case PRINT_C_CHAR:
  472. value = (signed char)va_arg(args, int);
  473. break;
  474. case PRINT_C_SHORT:
  475. value = (short int)va_arg(args, int);
  476. break;
  477. case PRINT_C_LONG:
  478. value = va_arg(args, long int);
  479. break;
  480. case PRINT_C_LLONG:
  481. value = va_arg(args, LLONG);
  482. break;
  483. case PRINT_C_SIZE:
  484. value = va_arg(args, SSIZE_T);
  485. break;
  486. case PRINT_C_INTMAX:
  487. value = va_arg(args, INTMAX_T);
  488. break;
  489. case PRINT_C_PTRDIFF:
  490. value = va_arg(args, PTRDIFF_T);
  491. break;
  492. default:
  493. value = va_arg(args, int);
  494. break;
  495. }
  496. fmtint(str, &len, size, value, 10, width,
  497. precision, flags);
  498. break;
  499. case 'X':
  500. flags |= PRINT_F_UP;
  501. /* FALLTHROUGH */
  502. case 'x':
  503. base = 16;
  504. /* FALLTHROUGH */
  505. case 'o':
  506. if (base == 0)
  507. base = 8;
  508. /* FALLTHROUGH */
  509. case 'u':
  510. if (base == 0)
  511. base = 10;
  512. flags |= PRINT_F_UNSIGNED;
  513. switch (cflags) {
  514. case PRINT_C_CHAR:
  515. value = (unsigned char)va_arg(args,
  516. unsigned int);
  517. break;
  518. case PRINT_C_SHORT:
  519. value = (unsigned short int)va_arg(args,
  520. unsigned int);
  521. break;
  522. case PRINT_C_LONG:
  523. value = va_arg(args, unsigned long int);
  524. break;
  525. case PRINT_C_LLONG:
  526. value = va_arg(args, ULLONG);
  527. break;
  528. case PRINT_C_SIZE:
  529. value = va_arg(args, size_t);
  530. break;
  531. case PRINT_C_INTMAX:
  532. value = va_arg(args, UINTMAX_T);
  533. break;
  534. case PRINT_C_PTRDIFF:
  535. value = va_arg(args, UPTRDIFF_T);
  536. break;
  537. default:
  538. value = va_arg(args, unsigned int);
  539. break;
  540. }
  541. fmtint(str, &len, size, value, base, width,
  542. precision, flags);
  543. break;
  544. case 'c':
  545. cvalue = va_arg(args, int);
  546. OUTCHAR(str, len, size, cvalue);
  547. break;
  548. case 's':
  549. strvalue = va_arg(args, char *);
  550. fmtstr(str, &len, size, strvalue, width,
  551. precision, flags);
  552. break;
  553. case 'p':
  554. /*
  555. * C99 says: "The value of the pointer is
  556. * converted to a sequence of printing
  557. * characters, in an implementation-defined
  558. * manner." (C99: 7.19.6.1, 8)
  559. */
  560. if ((strvalue = (const char*)va_arg(args, void *)) == NULL)
  561. /*
  562. * We use the glibc format. BSD prints
  563. * "0x0", SysV "0".
  564. */
  565. fmtstr(str, &len, size, "(nil)", width,
  566. -1, flags);
  567. else {
  568. /*
  569. * We use the BSD/glibc format. SysV
  570. * omits the "0x" prefix (which we emit
  571. * using the PRINT_F_NUM flag).
  572. */
  573. flags |= PRINT_F_NUM;
  574. flags |= PRINT_F_UNSIGNED;
  575. fmtint(str, &len, size,
  576. (UINTPTR_T)strvalue, 16, width,
  577. precision, flags);
  578. }
  579. break;
  580. case 'n':
  581. switch (cflags) {
  582. case PRINT_C_CHAR:
  583. charptr = va_arg(args, signed char *);
  584. *charptr = len;
  585. break;
  586. case PRINT_C_SHORT:
  587. shortptr = va_arg(args, short int *);
  588. *shortptr = len;
  589. break;
  590. case PRINT_C_LONG:
  591. longptr = va_arg(args, long int *);
  592. *longptr = len;
  593. break;
  594. case PRINT_C_LLONG:
  595. llongptr = va_arg(args, LLONG *);
  596. *llongptr = len;
  597. break;
  598. case PRINT_C_SIZE:
  599. /*
  600. * C99 says that with the "z" length
  601. * modifier, "a following `n' conversion
  602. * specifier applies to a pointer to a
  603. * signed integer type corresponding to
  604. * size_t argument." (7.19.6.1, 7)
  605. */
  606. sizeptr = va_arg(args, SSIZE_T *);
  607. *sizeptr = len;
  608. break;
  609. case PRINT_C_INTMAX:
  610. intmaxptr = va_arg(args, INTMAX_T *);
  611. *intmaxptr = len;
  612. break;
  613. case PRINT_C_PTRDIFF:
  614. ptrdiffptr = va_arg(args, PTRDIFF_T *);
  615. *ptrdiffptr = len;
  616. break;
  617. default:
  618. intptr = va_arg(args, int *);
  619. *intptr = len;
  620. break;
  621. }
  622. break;
  623. case '%': /* Print a "%" character verbatim. */
  624. OUTCHAR(str, len, size, ch);
  625. break;
  626. default: /* Skip other characters. */
  627. break;
  628. }
  629. ch = *format++;
  630. state = PRINT_S_DEFAULT;
  631. base = cflags = flags = width = 0;
  632. precision = -1;
  633. break;
  634. }
  635. out:
  636. if (len < size)
  637. str[len] = '\0';
  638. else if (size > 0)
  639. str[size - 1] = '\0';
  640.  
  641. if (overflow || len >= INT_MAX) {
  642. return -1;
  643. }
  644. return (int)len;
  645. }
  646.  
  647. static void
  648. fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
  649. int precision, int flags)
  650. {
  651. int padlen, strln; /* Amount to pad. */
  652. int noprecision = (precision == -1);
  653.  
  654. if (value == NULL) /* We're forgiving. */
  655. value = "(null)";
  656.  
  657. /* If a precision was specified, don't read the string past it. */
  658. for (strln = 0; value[strln] != '\0' &&
  659. (noprecision || strln < precision); strln++)
  660. continue;
  661.  
  662. if ((padlen = width - strln) < 0)
  663. padlen = 0;
  664. if (flags & PRINT_F_MINUS) /* Left justify. */
  665. padlen = -padlen;
  666.  
  667. while (padlen > 0) { /* Leading spaces. */
  668. OUTCHAR(str, *len, size, ' ');
  669. padlen--;
  670. }
  671. while (*value != '\0' && (noprecision || precision-- > 0)) {
  672. OUTCHAR(str, *len, size, *value);
  673. value++;
  674. }
  675. while (padlen < 0) { /* Trailing spaces. */
  676. OUTCHAR(str, *len, size, ' ');
  677. padlen++;
  678. }
  679. }
  680.  
  681. static void
  682. fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
  683. int precision, int flags)
  684. {
  685. UINTMAX_T uvalue;
  686. char iconvert[MAX_CONVERT_LENGTH];
  687. char sign = 0;
  688. char hexprefix = 0;
  689. int spadlen = 0; /* Amount to space pad. */
  690. int zpadlen = 0; /* Amount to zero pad. */
  691. int pos;
  692. int separators = (flags & PRINT_F_QUOTE);
  693. int noprecision = (precision == -1);
  694.  
  695. if (flags & PRINT_F_UNSIGNED)
  696. uvalue = value;
  697. else {
  698. uvalue = (value >= 0) ? value : -value;
  699. if (value < 0)
  700. sign = '-';
  701. else if (flags & PRINT_F_PLUS) /* Do a sign. */
  702. sign = '+';
  703. else if (flags & PRINT_F_SPACE)
  704. sign = ' ';
  705. }
  706.  
  707. pos = convert(uvalue, iconvert, sizeof(iconvert), base,
  708. flags & PRINT_F_UP);
  709.  
  710. if (flags & PRINT_F_NUM && uvalue != 0) {
  711. /*
  712. * C99 says: "The result is converted to an `alternative form'.
  713. * For `o' conversion, it increases the precision, if and only
  714. * if necessary, to force the first digit of the result to be a
  715. * zero (if the value and precision are both 0, a single 0 is
  716. * printed). For `x' (or `X') conversion, a nonzero result has
  717. * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
  718. */
  719. switch (base) {
  720. case 8:
  721. if (precision <= pos)
  722. precision = pos + 1;
  723. break;
  724. case 16:
  725. hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
  726. break;
  727. }
  728. }
  729.  
  730. if (separators) /* Get the number of group separators we'll print. */
  731. separators = getnumsep(pos);
  732.  
  733. zpadlen = precision - pos - separators;
  734. spadlen = width /* Minimum field width. */
  735. - separators /* Number of separators. */
  736. - MAX(precision, pos) /* Number of integer digits. */
  737. - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
  738. - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
  739.  
  740. if (zpadlen < 0)
  741. zpadlen = 0;
  742. if (spadlen < 0)
  743. spadlen = 0;
  744.  
  745. /*
  746. * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
  747. * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
  748. * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
  749. */
  750. if (flags & PRINT_F_MINUS) /* Left justify. */
  751. spadlen = -spadlen;
  752. else if (flags & PRINT_F_ZERO && noprecision) {
  753. zpadlen += spadlen;
  754. spadlen = 0;
  755. }
  756. while (spadlen > 0) { /* Leading spaces. */
  757. OUTCHAR(str, *len, size, ' ');
  758. spadlen--;
  759. }
  760. if (sign != 0) /* Sign. */
  761. OUTCHAR(str, *len, size, sign);
  762. if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
  763. OUTCHAR(str, *len, size, '0');
  764. OUTCHAR(str, *len, size, hexprefix);
  765. }
  766. while (zpadlen > 0) { /* Leading zeros. */
  767. OUTCHAR(str, *len, size, '0');
  768. zpadlen--;
  769. }
  770. while (pos > 0) { /* The actual digits. */
  771. pos--;
  772. OUTCHAR(str, *len, size, iconvert[pos]);
  773. if (separators > 0 && pos > 0 && pos % 3 == 0)
  774. printsep(str, len, size);
  775. }
  776. while (spadlen < 0) { /* Trailing spaces. */
  777. OUTCHAR(str, *len, size, ' ');
  778. spadlen++;
  779. }
  780. }
  781.  
  782.  
  783. static void
  784. printsep(char *str, size_t *len, size_t size)
  785. {
  786. OUTCHAR(str, *len, size, ',');
  787. }
  788.  
  789. static int
  790. getnumsep(int digits)
  791. {
  792. int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
  793. return separators;
  794. }
  795.  
  796. static int
  797. convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
  798. {
  799. const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
  800. size_t pos = 0;
  801.  
  802. /* We return an unterminated buffer with the digits in reverse order. */
  803. do {
  804. buf[pos++] = digits[value % base];
  805. value /= base;
  806. } while (value != 0 && pos < size);
  807.  
  808. return (int)pos;
  809. }
  810.  
  811. int vsprintf(char *buf, const char *fmt, va_list args)
  812. {
  813. return vsnprintf(buf, INT_MAX, fmt, args);
  814. }
  815.  
  816. int sprintf(char *buffer, const char *fmt, ...)
  817. {
  818. va_list args;
  819. int i;
  820.  
  821. va_start(args, fmt);
  822. i = vsprintf(buffer, fmt, args);
  823. va_end(args);
  824. return i;
  825. }
  826.  
  827. int snprintf(char *buffer, size_t len, const char *fmt, ...)
  828. {
  829. va_list args;
  830. int i;
  831.  
  832. va_start(args, fmt);
  833. i = vsnprintf(buffer, len, fmt, args);
  834. va_end(args);
  835. return i;
  836. }
  837.  
  838. #define PRINTF_MAX 128
  839.  
  840. #ifdef DEBUG_FILE
  841.  
  842. static int debug_fd = -1;
  843.  
  844. int printf(const char *fmt, ...)
  845. {
  846. char strBuf[PRINTF_MAX];
  847. va_list args;
  848. int i, written = 0;
  849.  
  850. va_start(args, fmt);
  851. i = vsnprintf(strBuf, PRINTF_MAX, fmt, args);
  852. va_end(args);
  853.  
  854.  
  855. if (debug_fd == -1)
  856. {
  857. int fd;
  858.  
  859. if (cellFsOpen("/dev_usb000/debug_log.txt", CELL_FS_O_WRONLY | CELL_FS_O_CREAT | CELL_FS_O_TRUNC, &fd, NULL, 0) == 0)
  860. {
  861. debug_fd = fd;
  862. }
  863. }
  864.  
  865. if (debug_fd >= 0)
  866. {
  867. cellFsWrite(debug_fd, strBuf, i, NULL);
  868. }
  869.  
  870. return written;
  871. }
  872.  
  873. #else
  874.  
  875. int console_print(char* a_szText)
  876. {
  877. uint32_t l_uiTextLen;
  878. uint32_t l_uiWriteLen;
  879.  
  880. l_uiWriteLen = 0;
  881. //strlen
  882. l_uiTextLen = 0;
  883. while (a_szText[l_uiTextLen] != 0) l_uiTextLen++;
  884. system_call_4(403, 0, (uint64_t)a_szText, l_uiTextLen, (uint64_t)&l_uiWriteLen);
  885. return (l_uiTextLen == l_uiWriteLen);
  886. }
  887.  
  888.  
  889.  
  890.  
  891. int printf(const char *fmt, ...)
  892. {
  893. char strBuf[PRINTF_MAX];
  894. int l_iLen;
  895.  
  896. va_list args;
  897. va_start(args, fmt);
  898.  
  899.  
  900. vsnprintf(strBuf, PRINTF_MAX, fmt, args);
  901.  
  902. va_end(args);
  903. console_print(strBuf);
  904. return 0;
  905. }
  906.  
  907. };
  908. #endif /* DEBUG_FILE */
  909.  
  910. //#endif /* DEBUG */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement