You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1335 lines
31 KiB

12 years ago
13 years ago
28 years ago
19 years ago
28 years ago
28 years ago
19 years ago
19 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
19 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
19 years ago
28 years ago
28 years ago
28 years ago
20 years ago
20 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
19 years ago
28 years ago
19 years ago
28 years ago
19 years ago
28 years ago
28 years ago
19 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
28 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2014 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #define _GNU_SOURCE
  20. #include "php.h"
  21. #include <zend_strtod.h>
  22. #include <stddef.h>
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include <sys/types.h>
  26. #include <stdarg.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <math.h>
  30. #ifdef HAVE_INTTYPES_H
  31. #include <inttypes.h>
  32. #endif
  33. #ifdef HAVE_LOCALE_H
  34. #include <locale.h>
  35. #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
  36. #else
  37. #define LCONV_DECIMAL_POINT '.'
  38. #endif
  39. /*
  40. * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
  41. *
  42. * Permission to use, copy, modify, and distribute this software for any
  43. * purpose with or without fee is hereby granted, provided that the above
  44. * copyright notice and this permission notice appear in all copies.
  45. *
  46. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  47. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  48. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  49. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  50. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  51. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  52. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  53. *
  54. * Sponsored in part by the Defense Advanced Research Projects
  55. * Agency (DARPA) and Air Force Research Laboratory, Air Force
  56. * Materiel Command, USAF, under agreement number F39502-99-1-0512.
  57. */
  58. static char * __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) /* {{{ */
  59. {
  60. register char *s = NULL;
  61. char *p, *rve, c;
  62. size_t siz;
  63. if (ndigit < 0) {
  64. siz = -ndigit + 1;
  65. } else {
  66. siz = ndigit + 1;
  67. }
  68. /* __dtoa() doesn't allocate space for 0 so we do it by hand */
  69. if (value == 0.0) {
  70. *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
  71. *sign = 0;
  72. if ((rve = s = (char *)malloc(ndigit?siz:2)) == NULL) {
  73. return(NULL);
  74. }
  75. *rve++ = '0';
  76. *rve = '\0';
  77. if (!ndigit) {
  78. return(s);
  79. }
  80. } else {
  81. p = zend_dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
  82. if (*decpt == 9999) {
  83. /* Infinity or Nan, convert to inf or nan like printf */
  84. *decpt = 0;
  85. c = *p;
  86. zend_freedtoa(p);
  87. return strdup((c == 'I' ? "INF" : "NAN"));
  88. }
  89. /* Make a local copy and adjust rve to be in terms of s */
  90. if (pad && fmode) {
  91. siz += *decpt;
  92. }
  93. if ((s = (char *)malloc(siz+1)) == NULL) {
  94. zend_freedtoa(p);
  95. return(NULL);
  96. }
  97. (void) strlcpy(s, p, siz);
  98. rve = s + (rve - p);
  99. zend_freedtoa(p);
  100. }
  101. /* Add trailing zeros */
  102. if (pad) {
  103. siz -= rve - s;
  104. while (--siz) {
  105. *rve++ = '0';
  106. }
  107. *rve = '\0';
  108. }
  109. return(s);
  110. }
  111. /* }}} */
  112. static inline char *php_ecvt(double value, int ndigit, int *decpt, int *sign) /* {{{ */
  113. {
  114. return(__cvt(value, ndigit, decpt, sign, 0, 1));
  115. }
  116. /* }}} */
  117. static inline char *php_fcvt(double value, int ndigit, int *decpt, int *sign) /* {{{ */
  118. {
  119. return(__cvt(value, ndigit, decpt, sign, 1, 1));
  120. }
  121. /* }}} */
  122. PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */
  123. {
  124. char *digits, *dst, *src;
  125. int i, decpt, sign;
  126. digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL);
  127. if (decpt == 9999) {
  128. /*
  129. * Infinity or NaN, convert to inf or nan with sign.
  130. * We assume the buffer is at least ndigit long.
  131. */
  132. snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
  133. zend_freedtoa(digits);
  134. return (buf);
  135. }
  136. dst = buf;
  137. if (sign) {
  138. *dst++ = '-';
  139. }
  140. if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
  141. /* exponential format (e.g. 1.2345e+13) */
  142. if (--decpt < 0) {
  143. sign = 1;
  144. decpt = -decpt;
  145. } else {
  146. sign = 0;
  147. }
  148. src = digits;
  149. *dst++ = *src++;
  150. *dst++ = dec_point;
  151. if (*src == '\0') {
  152. *dst++ = '0';
  153. } else {
  154. do {
  155. *dst++ = *src++;
  156. } while (*src != '\0');
  157. }
  158. *dst++ = exponent;
  159. if (sign) {
  160. *dst++ = '-';
  161. } else {
  162. *dst++ = '+';
  163. }
  164. if (decpt < 10) {
  165. *dst++ = '0' + decpt;
  166. *dst = '\0';
  167. } else {
  168. /* XXX - optimize */
  169. for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
  170. continue;
  171. dst[i + 1] = '\0';
  172. while (decpt != 0) {
  173. dst[i--] = '0' + decpt % 10;
  174. decpt /= 10;
  175. }
  176. }
  177. } else if (decpt < 0) {
  178. /* standard format 0. */
  179. *dst++ = '0'; /* zero before decimal point */
  180. *dst++ = dec_point;
  181. do {
  182. *dst++ = '0';
  183. } while (++decpt < 0);
  184. src = digits;
  185. while (*src != '\0') {
  186. *dst++ = *src++;
  187. }
  188. *dst = '\0';
  189. } else {
  190. /* standard format */
  191. for (i = 0, src = digits; i < decpt; i++) {
  192. if (*src != '\0') {
  193. *dst++ = *src++;
  194. } else {
  195. *dst++ = '0';
  196. }
  197. }
  198. if (*src != '\0') {
  199. if (src == digits) {
  200. *dst++ = '0'; /* zero before decimal point */
  201. }
  202. *dst++ = dec_point;
  203. for (i = decpt; digits[i] != '\0'; i++) {
  204. *dst++ = digits[i];
  205. }
  206. }
  207. *dst = '\0';
  208. }
  209. zend_freedtoa(digits);
  210. return (buf);
  211. }
  212. /* }}} */
  213. /* {{{ Apache license */
  214. /* ====================================================================
  215. * Copyright (c) 1995-1998 The Apache Group. All rights reserved.
  216. *
  217. * Redistribution and use in source and binary forms, with or without
  218. * modification, are permitted provided that the following conditions
  219. * are met:
  220. *
  221. * 1. Redistributions of source code must retain the above copyright
  222. * notice, this list of conditions and the following disclaimer.
  223. *
  224. * 2. Redistributions in binary form must reproduce the above copyright
  225. * notice, this list of conditions and the following disclaimer in
  226. * the documentation and/or other materials provided with the
  227. * distribution.
  228. *
  229. * 3. All advertising materials mentioning features or use of this
  230. * software must display the following acknowledgment:
  231. * "This product includes software developed by the Apache Group
  232. * for use in the Apache HTTP server project (http://www.apache.org/)."
  233. *
  234. * 4. The names "Apache Server" and "Apache Group" must not be used to
  235. * endorse or promote products derived from this software without
  236. * prior written permission.
  237. *
  238. * 5. Redistributions of any form whatsoever must retain the following
  239. * acknowledgment:
  240. * "This product includes software developed by the Apache Group
  241. * for use in the Apache HTTP server project (http://www.apache.org/)."
  242. *
  243. * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  244. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  245. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  246. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
  247. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  248. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  249. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  250. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  251. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  252. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  253. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  254. * OF THE POSSIBILITY OF SUCH DAMAGE.
  255. * ====================================================================
  256. *
  257. * This software consists of voluntary contributions made by many
  258. * individuals on behalf of the Apache Group and was originally based
  259. * on public domain software written at the National Center for
  260. * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  261. * For more information on the Apache Group and the Apache HTTP server
  262. * project, please see <http://www.apache.org/>.
  263. *
  264. * This code is based on, and used with the permission of, the
  265. * SIO stdio-replacement strx_* functions by Panos Tsirigotis
  266. * <panos@alumni.cs.colorado.edu> for xinetd.
  267. */
  268. /* }}} */
  269. #define FALSE 0
  270. #define TRUE 1
  271. #define NUL '\0'
  272. #define INT_NULL ((int *)0)
  273. #define S_NULL "(null)"
  274. #define S_NULL_LEN 6
  275. #define FLOAT_DIGITS 6
  276. #define EXPONENT_LENGTH 10
  277. /*
  278. * Convert num to its decimal format.
  279. * Return value:
  280. * - a pointer to a string containing the number (no sign)
  281. * - len contains the length of the string
  282. * - is_negative is set to TRUE or FALSE depending on the sign
  283. * of the number (always set to FALSE if is_unsigned is TRUE)
  284. *
  285. * The caller provides a buffer for the string: that is the buf_end argument
  286. * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  287. * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  288. */
  289. /* char * ap_php_conv_10() {{{ */
  290. char * ap_php_conv_10(register wide_int num, register bool_int is_unsigned,
  291. register bool_int * is_negative, char *buf_end, register size_t *len)
  292. {
  293. register char *p = buf_end;
  294. register u_wide_int magnitude;
  295. if (is_unsigned) {
  296. magnitude = (u_wide_int) num;
  297. *is_negative = FALSE;
  298. } else {
  299. *is_negative = (num < 0);
  300. /*
  301. * On a 2's complement machine, negating the most negative integer
  302. * results in a number that cannot be represented as a signed integer.
  303. * Here is what we do to obtain the number's magnitude:
  304. * a. add 1 to the number
  305. * b. negate it (becomes positive)
  306. * c. convert it to unsigned
  307. * d. add 1
  308. */
  309. if (*is_negative) {
  310. wide_int t = num + 1;
  311. magnitude = ((u_wide_int) - t) + 1;
  312. } else {
  313. magnitude = (u_wide_int) num;
  314. }
  315. }
  316. /*
  317. * We use a do-while loop so that we write at least 1 digit
  318. */
  319. do {
  320. register u_wide_int new_magnitude = magnitude / 10;
  321. *--p = (char)(magnitude - new_magnitude * 10 + '0');
  322. magnitude = new_magnitude;
  323. }
  324. while (magnitude);
  325. *len = buf_end - p;
  326. return (p);
  327. }
  328. /* }}} */
  329. /* If you change this value then also change bug24640.phpt.
  330. * Also NDIG must be reasonable smaller than NUM_BUF_SIZE.
  331. */
  332. #define NDIG 320
  333. /*
  334. * Convert a floating point number to a string formats 'f', 'e' or 'E'.
  335. * The result is placed in buf, and len denotes the length of the string
  336. * The sign is returned in the is_negative argument (and is not placed
  337. * in buf).
  338. */
  339. /* PHPAPI char * php_conv_fp() {{{ */
  340. PHPAPI char * php_conv_fp(register char format, register double num,
  341. boolean_e add_dp, int precision, char dec_point, bool_int * is_negative, char *buf, size_t *len)
  342. {
  343. register char *s = buf;
  344. register char *p, *p_orig;
  345. int decimal_point;
  346. if (precision >= NDIG - 1) {
  347. precision = NDIG - 2;
  348. }
  349. if (format == 'F') {
  350. p_orig = p = php_fcvt(num, precision, &decimal_point, is_negative);
  351. } else { /* either e or E format */
  352. p_orig = p = php_ecvt(num, precision + 1, &decimal_point, is_negative);
  353. }
  354. /*
  355. * Check for Infinity and NaN
  356. */
  357. if (isalpha((int)*p)) {
  358. *len = strlen(p);
  359. memcpy(buf, p, *len + 1);
  360. *is_negative = FALSE;
  361. free(p_orig);
  362. return (buf);
  363. }
  364. if (format == 'F') {
  365. if (decimal_point <= 0) {
  366. if (num != 0 || precision > 0) {
  367. *s++ = '0';
  368. if (precision > 0) {
  369. *s++ = dec_point;
  370. while (decimal_point++ < 0) {
  371. *s++ = '0';
  372. }
  373. } else if (add_dp) {
  374. *s++ = dec_point;
  375. }
  376. }
  377. } else {
  378. int addz = decimal_point >= NDIG ? decimal_point - NDIG + 1 : 0;
  379. decimal_point -= addz;
  380. while (decimal_point-- > 0) {
  381. *s++ = *p++;
  382. }
  383. while (addz-- > 0) {
  384. *s++ = '0';
  385. }
  386. if (precision > 0 || add_dp) {
  387. *s++ = dec_point;
  388. }
  389. }
  390. } else {
  391. *s++ = *p++;
  392. if (precision > 0 || add_dp) {
  393. *s++ = '.';
  394. }
  395. }
  396. /*
  397. * copy the rest of p, the NUL is NOT copied
  398. */
  399. while (*p) {
  400. *s++ = *p++;
  401. }
  402. if (format != 'F') {
  403. char temp[EXPONENT_LENGTH]; /* for exponent conversion */
  404. size_t t_len;
  405. bool_int exponent_is_negative;
  406. *s++ = format; /* either e or E */
  407. decimal_point--;
  408. if (decimal_point != 0) {
  409. p = ap_php_conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, &temp[EXPONENT_LENGTH], &t_len);
  410. *s++ = exponent_is_negative ? '-' : '+';
  411. /*
  412. * Make sure the exponent has at least 2 digits
  413. */
  414. while (t_len--) {
  415. *s++ = *p++;
  416. }
  417. } else {
  418. *s++ = '+';
  419. *s++ = '0';
  420. }
  421. }
  422. *len = s - buf;
  423. free(p_orig);
  424. return (buf);
  425. }
  426. /* }}} */
  427. /*
  428. * Convert num to a base X number where X is a power of 2. nbits determines X.
  429. * For example, if nbits is 3, we do base 8 conversion
  430. * Return value:
  431. * a pointer to a string containing the number
  432. *
  433. * The caller provides a buffer for the string: that is the buf_end argument
  434. * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  435. * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  436. */
  437. char * ap_php_conv_p2(register u_wide_int num, register int nbits, char format, char *buf_end, register size_t *len) /* {{{ */
  438. {
  439. register int mask = (1 << nbits) - 1;
  440. register char *p = buf_end;
  441. static char low_digits[] = "0123456789abcdef";
  442. static char upper_digits[] = "0123456789ABCDEF";
  443. register char *digits = (format == 'X') ? upper_digits : low_digits;
  444. do {
  445. *--p = digits[num & mask];
  446. num >>= nbits;
  447. }
  448. while (num);
  449. *len = buf_end - p;
  450. return (p);
  451. }
  452. /* }}} */
  453. /*
  454. * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
  455. *
  456. * XXX: this is a magic number; do not decrease it
  457. * Emax = 1023
  458. * NDIG = 320
  459. * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
  460. */
  461. #define NUM_BUF_SIZE 2048
  462. /*
  463. * Descriptor for buffer area
  464. */
  465. struct buf_area {
  466. char *buf_end;
  467. char *nextb; /* pointer to next byte to read/write */
  468. };
  469. typedef struct buf_area buffy;
  470. /*
  471. * The INS_CHAR macro inserts a character in the buffer and writes
  472. * the buffer back to disk if necessary
  473. * It uses the char pointers sp and bep:
  474. * sp points to the next available character in the buffer
  475. * bep points to the end-of-buffer+1
  476. * While using this macro, note that the nextb pointer is NOT updated.
  477. *
  478. * NOTE: Evaluation of the c argument should not have any side-effects
  479. */
  480. #define INS_CHAR(c, sp, bep, cc) \
  481. { \
  482. if (sp < bep) \
  483. { \
  484. *sp++ = c; \
  485. } \
  486. cc++; \
  487. }
  488. #define NUM( c ) ( c - '0' )
  489. #define STR_TO_DEC( str, num ) \
  490. num = NUM( *str++ ) ; \
  491. while ( isdigit((int)*str ) ) \
  492. { \
  493. num *= 10 ; \
  494. num += NUM( *str++ ) ; \
  495. }
  496. /*
  497. * This macro does zero padding so that the precision
  498. * requirement is satisfied. The padding is done by
  499. * adding '0's to the left of the string that is going
  500. * to be printed.
  501. */
  502. #define FIX_PRECISION( adjust, precision, s, s_len ) \
  503. if ( adjust ) \
  504. while ( s_len < precision ) \
  505. { \
  506. *--s = '0' ; \
  507. s_len++ ; \
  508. }
  509. /*
  510. * Macro that does padding. The padding is done by printing
  511. * the character ch.
  512. */
  513. #define PAD( width, len, ch ) do \
  514. { \
  515. INS_CHAR( ch, sp, bep, cc ) ; \
  516. width-- ; \
  517. } \
  518. while ( width > len )
  519. /*
  520. * Prefix the character ch to the string str
  521. * Increase length
  522. * Set the has_prefix flag
  523. */
  524. #define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES
  525. /*
  526. * Do format conversion placing the output in buffer
  527. */
  528. static int format_converter(register buffy * odp, const char *fmt, va_list ap) /* {{{ */
  529. {
  530. char *sp;
  531. char *bep;
  532. int cc = 0;
  533. size_t i;
  534. char *s = NULL;
  535. size_t s_len;
  536. int free_zcopy;
  537. zval *zvp, zcopy;
  538. int min_width = 0;
  539. int precision = 0;
  540. enum {
  541. LEFT, RIGHT
  542. } adjust;
  543. char pad_char;
  544. char prefix_char;
  545. double fp_num;
  546. wide_int i_num = (wide_int) 0;
  547. u_wide_int ui_num;
  548. char num_buf[NUM_BUF_SIZE];
  549. char char_buf[2]; /* for printing %% and %<unknown> */
  550. #ifdef HAVE_LOCALE_H
  551. struct lconv *lconv = NULL;
  552. #endif
  553. /*
  554. * Flag variables
  555. */
  556. length_modifier_e modifier;
  557. boolean_e alternate_form;
  558. boolean_e print_sign;
  559. boolean_e print_blank;
  560. boolean_e adjust_precision;
  561. boolean_e adjust_width;
  562. bool_int is_negative;
  563. sp = odp->nextb;
  564. bep = odp->buf_end;
  565. while (*fmt) {
  566. if (*fmt != '%') {
  567. INS_CHAR(*fmt, sp, bep, cc);
  568. } else {
  569. /*
  570. * Default variable settings
  571. */
  572. adjust = RIGHT;
  573. alternate_form = print_sign = print_blank = NO;
  574. pad_char = ' ';
  575. prefix_char = NUL;
  576. free_zcopy = 0;
  577. fmt++;
  578. /*
  579. * Try to avoid checking for flags, width or precision
  580. */
  581. if (isascii((int)*fmt) && !islower((int)*fmt)) {
  582. /*
  583. * Recognize flags: -, #, BLANK, +
  584. */
  585. for (;; fmt++) {
  586. if (*fmt == '-')
  587. adjust = LEFT;
  588. else if (*fmt == '+')
  589. print_sign = YES;
  590. else if (*fmt == '#')
  591. alternate_form = YES;
  592. else if (*fmt == ' ')
  593. print_blank = YES;
  594. else if (*fmt == '0')
  595. pad_char = '0';
  596. else
  597. break;
  598. }
  599. /*
  600. * Check if a width was specified
  601. */
  602. if (isdigit((int)*fmt)) {
  603. STR_TO_DEC(fmt, min_width);
  604. adjust_width = YES;
  605. } else if (*fmt == '*') {
  606. min_width = va_arg(ap, int);
  607. fmt++;
  608. adjust_width = YES;
  609. if (min_width < 0) {
  610. adjust = LEFT;
  611. min_width = -min_width;
  612. }
  613. } else
  614. adjust_width = NO;
  615. /*
  616. * Check if a precision was specified
  617. */
  618. if (*fmt == '.') {
  619. adjust_precision = YES;
  620. fmt++;
  621. if (isdigit((int)*fmt)) {
  622. STR_TO_DEC(fmt, precision);
  623. } else if (*fmt == '*') {
  624. precision = va_arg(ap, int);
  625. fmt++;
  626. if (precision < 0)
  627. precision = 0;
  628. } else
  629. precision = 0;
  630. if (precision > FORMAT_CONV_MAX_PRECISION) {
  631. precision = FORMAT_CONV_MAX_PRECISION;
  632. }
  633. } else
  634. adjust_precision = NO;
  635. } else
  636. adjust_precision = adjust_width = NO;
  637. /*
  638. * Modifier check
  639. */
  640. switch (*fmt) {
  641. case 'L':
  642. fmt++;
  643. modifier = LM_LONG_DOUBLE;
  644. break;
  645. case 'I':
  646. fmt++;
  647. #if SIZEOF_LONG_LONG
  648. if (*fmt == '6' && *(fmt+1) == '4') {
  649. fmt += 2;
  650. modifier = LM_LONG_LONG;
  651. } else
  652. #endif
  653. if (*fmt == '3' && *(fmt+1) == '2') {
  654. fmt += 2;
  655. modifier = LM_LONG;
  656. } else {
  657. #ifdef _WIN64
  658. modifier = LM_LONG_LONG;
  659. #else
  660. modifier = LM_LONG;
  661. #endif
  662. }
  663. break;
  664. case 'l':
  665. fmt++;
  666. #if SIZEOF_LONG_LONG
  667. if (*fmt == 'l') {
  668. fmt++;
  669. modifier = LM_LONG_LONG;
  670. } else
  671. #endif
  672. modifier = LM_LONG;
  673. break;
  674. case 'z':
  675. fmt++;
  676. modifier = LM_SIZE_T;
  677. break;
  678. case 'j':
  679. fmt++;
  680. #if SIZEOF_INTMAX_T
  681. modifier = LM_INTMAX_T;
  682. #else
  683. modifier = LM_SIZE_T;
  684. #endif
  685. break;
  686. case 't':
  687. fmt++;
  688. #if SIZEOF_PTRDIFF_T
  689. modifier = LM_PTRDIFF_T;
  690. #else
  691. modifier = LM_SIZE_T;
  692. #endif
  693. break;
  694. case 'p':
  695. fmt++;
  696. modifier = LM_PHP_INT_T;
  697. break;
  698. case 'h':
  699. fmt++;
  700. if (*fmt == 'h') {
  701. fmt++;
  702. }
  703. /* these are promoted to int, so no break */
  704. default:
  705. modifier = LM_STD;
  706. break;
  707. }
  708. /*
  709. * Argument extraction and printing.
  710. * First we determine the argument type.
  711. * Then, we convert the argument to a string.
  712. * On exit from the switch, s points to the string that
  713. * must be printed, s_len has the length of the string
  714. * The precision requirements, if any, are reflected in s_len.
  715. *
  716. * NOTE: pad_char may be set to '0' because of the 0 flag.
  717. * It is reset to ' ' by non-numeric formats
  718. */
  719. switch (*fmt) {
  720. case 'Z': {
  721. TSRMLS_FETCH();
  722. zvp = (zval*) va_arg(ap, zval*);
  723. free_zcopy = zend_make_printable_zval(zvp, &zcopy TSRMLS_CC);
  724. if (free_zcopy) {
  725. zvp = &zcopy;
  726. }
  727. s_len = Z_STRLEN_P(zvp);
  728. s = Z_STRVAL_P(zvp);
  729. if (adjust_precision && precision < s_len) {
  730. s_len = precision;
  731. }
  732. break;
  733. }
  734. case 'u':
  735. switch(modifier) {
  736. default:
  737. i_num = (wide_int) va_arg(ap, unsigned int);
  738. break;
  739. case LM_LONG_DOUBLE:
  740. goto fmt_error;
  741. case LM_LONG:
  742. i_num = (wide_int) va_arg(ap, unsigned long int);
  743. break;
  744. case LM_SIZE_T:
  745. i_num = (wide_int) va_arg(ap, size_t);
  746. break;
  747. #if SIZEOF_LONG_LONG
  748. case LM_LONG_LONG:
  749. i_num = (wide_int) va_arg(ap, u_wide_int);
  750. break;
  751. #endif
  752. #if SIZEOF_INTMAX_T
  753. case LM_INTMAX_T:
  754. i_num = (wide_int) va_arg(ap, uintmax_t);
  755. break;
  756. #endif
  757. #if SIZEOF_PTRDIFF_T
  758. case LM_PTRDIFF_T:
  759. i_num = (wide_int) va_arg(ap, ptrdiff_t);
  760. break;
  761. #endif
  762. case LM_PHP_INT_T:
  763. i_num = (wide_int) va_arg(ap, zend_ulong);
  764. break;
  765. }
  766. /*
  767. * The rest also applies to other integer formats, so fall
  768. * into that case.
  769. */
  770. case 'd':
  771. case 'i':
  772. /*
  773. * Get the arg if we haven't already.
  774. */
  775. if ((*fmt) != 'u') {
  776. switch(modifier) {
  777. default:
  778. i_num = (wide_int) va_arg(ap, int);
  779. break;
  780. case LM_LONG_DOUBLE:
  781. goto fmt_error;
  782. case LM_LONG:
  783. i_num = (wide_int) va_arg(ap, long int);
  784. break;
  785. case LM_SIZE_T:
  786. #if SIZEOF_SSIZE_T
  787. i_num = (wide_int) va_arg(ap, ssize_t);
  788. #else
  789. i_num = (wide_int) va_arg(ap, size_t);
  790. #endif
  791. break;
  792. #if SIZEOF_LONG_LONG
  793. case LM_LONG_LONG:
  794. i_num = (wide_int) va_arg(ap, wide_int);
  795. break;
  796. #endif
  797. #if SIZEOF_INTMAX_T
  798. case LM_INTMAX_T:
  799. i_num = (wide_int) va_arg(ap, intmax_t);
  800. break;
  801. #endif
  802. #if SIZEOF_PTRDIFF_T
  803. case LM_PTRDIFF_T:
  804. i_num = (wide_int) va_arg(ap, ptrdiff_t);
  805. break;
  806. #endif
  807. case LM_PHP_INT_T:
  808. i_num = (wide_int) va_arg(ap, zend_long);
  809. break;
  810. }
  811. }
  812. s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
  813. &num_buf[NUM_BUF_SIZE], &s_len);
  814. FIX_PRECISION(adjust_precision, precision, s, s_len);
  815. if (*fmt != 'u') {
  816. if (is_negative) {
  817. prefix_char = '-';
  818. } else if (print_sign) {
  819. prefix_char = '+';
  820. } else if (print_blank) {
  821. prefix_char = ' ';
  822. }
  823. }
  824. break;
  825. case 'o':
  826. switch(modifier) {
  827. default:
  828. ui_num = (u_wide_int) va_arg(ap, unsigned int);
  829. break;
  830. case LM_LONG_DOUBLE:
  831. goto fmt_error;
  832. case LM_LONG:
  833. ui_num = (u_wide_int) va_arg(ap, unsigned long int);
  834. break;
  835. case LM_SIZE_T:
  836. ui_num = (u_wide_int) va_arg(ap, size_t);
  837. break;
  838. #if SIZEOF_LONG_LONG
  839. case LM_LONG_LONG:
  840. ui_num = (u_wide_int) va_arg(ap, u_wide_int);
  841. break;
  842. #endif
  843. #if SIZEOF_INTMAX_T
  844. case LM_INTMAX_T:
  845. ui_num = (u_wide_int) va_arg(ap, uintmax_t);
  846. break;
  847. #endif
  848. #if SIZEOF_PTRDIFF_T
  849. case LM_PTRDIFF_T:
  850. ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
  851. break;
  852. #endif
  853. case LM_PHP_INT_T:
  854. ui_num = (u_wide_int) va_arg(ap, zend_ulong);
  855. break;
  856. }
  857. s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
  858. FIX_PRECISION(adjust_precision, precision, s, s_len);
  859. if (alternate_form && *s != '0') {
  860. *--s = '0';
  861. s_len++;
  862. }
  863. break;
  864. case 'x':
  865. case 'X':
  866. switch(modifier) {
  867. default:
  868. ui_num = (u_wide_int) va_arg(ap, unsigned int);
  869. break;
  870. case LM_LONG_DOUBLE:
  871. goto fmt_error;
  872. case LM_LONG:
  873. ui_num = (u_wide_int) va_arg(ap, unsigned long int);
  874. break;
  875. case LM_SIZE_T:
  876. ui_num = (u_wide_int) va_arg(ap, size_t);
  877. break;
  878. #if SIZEOF_LONG_LONG
  879. case LM_LONG_LONG:
  880. ui_num = (u_wide_int) va_arg(ap, u_wide_int);
  881. break;
  882. #endif
  883. #if SIZEOF_INTMAX_T
  884. case LM_INTMAX_T:
  885. ui_num = (u_wide_int) va_arg(ap, uintmax_t);
  886. break;
  887. #endif
  888. #if SIZEOF_PTRDIFF_T
  889. case LM_PTRDIFF_T:
  890. ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
  891. break;
  892. #endif
  893. case LM_PHP_INT_T:
  894. ui_num = (u_wide_int) va_arg(ap, zend_ulong);
  895. break;
  896. }
  897. s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
  898. FIX_PRECISION(adjust_precision, precision, s, s_len);
  899. if (alternate_form && i_num != 0) {
  900. *--s = *fmt; /* 'x' or 'X' */
  901. *--s = '0';
  902. s_len += 2;
  903. }
  904. break;
  905. case 's':
  906. case 'v':
  907. s = va_arg(ap, char *);
  908. if (s != NULL) {
  909. s_len = strlen(s);
  910. if (adjust_precision && precision < s_len) {
  911. s_len = precision;
  912. }
  913. } else {
  914. s = S_NULL;
  915. s_len = S_NULL_LEN;
  916. }
  917. pad_char = ' ';
  918. break;
  919. case 'f':
  920. case 'F':
  921. case 'e':
  922. case 'E':
  923. switch(modifier) {
  924. case LM_LONG_DOUBLE:
  925. fp_num = (double) va_arg(ap, long double);
  926. break;
  927. case LM_STD:
  928. fp_num = va_arg(ap, double);
  929. break;
  930. default:
  931. goto fmt_error;
  932. }
  933. if (zend_isnan(fp_num)) {
  934. s = "NAN";
  935. s_len = 3;
  936. } else if (zend_isinf(fp_num)) {
  937. s = "INF";
  938. s_len = 3;
  939. } else {
  940. #ifdef HAVE_LOCALE_H
  941. if (!lconv) {
  942. lconv = localeconv();
  943. }
  944. #endif
  945. s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
  946. (adjust_precision == NO) ? FLOAT_DIGITS : precision,
  947. (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
  948. &is_negative, &num_buf[1], &s_len);
  949. if (is_negative)
  950. prefix_char = '-';
  951. else if (print_sign)
  952. prefix_char = '+';
  953. else if (print_blank)
  954. prefix_char = ' ';
  955. }
  956. break;
  957. case 'g':
  958. case 'k':
  959. case 'G':
  960. case 'H':
  961. switch(modifier) {
  962. case LM_LONG_DOUBLE:
  963. fp_num = (double) va_arg(ap, long double);
  964. break;
  965. case LM_STD:
  966. fp_num = va_arg(ap, double);
  967. break;
  968. default:
  969. goto fmt_error;
  970. }
  971. if (zend_isnan(fp_num)) {
  972. s = "NAN";
  973. s_len = 3;
  974. break;
  975. } else if (zend_isinf(fp_num)) {
  976. if (fp_num > 0) {
  977. s = "INF";
  978. s_len = 3;
  979. } else {
  980. s = "-INF";
  981. s_len = 4;
  982. }
  983. break;
  984. }
  985. if (adjust_precision == NO) {
  986. precision = FLOAT_DIGITS;
  987. } else if (precision == 0) {
  988. precision = 1;
  989. }
  990. /*
  991. * * We use &num_buf[ 1 ], so that we have room for the sign
  992. */
  993. #ifdef HAVE_LOCALE_H
  994. if (!lconv) {
  995. lconv = localeconv();
  996. }
  997. #endif
  998. s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
  999. if (*s == '-') {
  1000. prefix_char = *s++;
  1001. } else if (print_sign) {
  1002. prefix_char = '+';
  1003. } else if (print_blank) {
  1004. prefix_char = ' ';
  1005. }
  1006. s_len = strlen(s);
  1007. if (alternate_form && (strchr(s, '.')) == NULL) {
  1008. s[s_len++] = '.';
  1009. }
  1010. break;
  1011. case 'c':
  1012. char_buf[0] = (char) (va_arg(ap, int));
  1013. s = &char_buf[0];
  1014. s_len = 1;
  1015. pad_char = ' ';
  1016. break;
  1017. case '%':
  1018. char_buf[0] = '%';
  1019. s = &char_buf[0];
  1020. s_len = 1;
  1021. pad_char = ' ';
  1022. break;
  1023. case 'n':
  1024. *(va_arg(ap, int *)) = cc;
  1025. goto skip_output;
  1026. /*
  1027. * Always extract the argument as a "char *" pointer. We
  1028. * should be using "void *" but there are still machines
  1029. * that don't understand it.
  1030. * If the pointer size is equal to the size of an unsigned
  1031. * integer we convert the pointer to a hex number, otherwise
  1032. * we print "%p" to indicate that we don't handle "%p".
  1033. */
  1034. case 'p':
  1035. if (sizeof(char *) <= sizeof(u_wide_int)) {
  1036. ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
  1037. s = ap_php_conv_p2(ui_num, 4, 'x',
  1038. &num_buf[NUM_BUF_SIZE], &s_len);
  1039. if (ui_num != 0) {
  1040. *--s = 'x';
  1041. *--s = '0';
  1042. s_len += 2;
  1043. }
  1044. } else {
  1045. s = "%p";
  1046. s_len = 2;
  1047. }
  1048. pad_char = ' ';
  1049. break;
  1050. case NUL:
  1051. /*
  1052. * The last character of the format string was %.
  1053. * We ignore it.
  1054. */
  1055. continue;
  1056. fmt_error:
  1057. php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
  1058. /*
  1059. * The default case is for unrecognized %'s.
  1060. * We print %<char> to help the user identify what
  1061. * option is not understood.
  1062. * This is also useful in case the user wants to pass
  1063. * the output of format_converter to another function
  1064. * that understands some other %<char> (like syslog).
  1065. * Note that we can't point s inside fmt because the
  1066. * unknown <char> could be preceded by width etc.
  1067. */
  1068. default:
  1069. char_buf[0] = '%';
  1070. char_buf[1] = *fmt;
  1071. s = char_buf;
  1072. s_len = 2;
  1073. pad_char = ' ';
  1074. break;
  1075. }
  1076. if (prefix_char != NUL) {
  1077. *--s = prefix_char;
  1078. s_len++;
  1079. }
  1080. if (adjust_width && adjust == RIGHT && min_width > s_len) {
  1081. if (pad_char == '0' && prefix_char != NUL) {
  1082. INS_CHAR(*s, sp, bep, cc)
  1083. s++;
  1084. s_len--;
  1085. min_width--;
  1086. }
  1087. PAD(min_width, s_len, pad_char);
  1088. }
  1089. /*
  1090. * Print the string s.
  1091. */
  1092. for (i = s_len; i != 0; i--) {
  1093. INS_CHAR(*s, sp, bep, cc);
  1094. s++;
  1095. }
  1096. if (adjust_width && adjust == LEFT && min_width > s_len)
  1097. PAD(min_width, s_len, pad_char);
  1098. if (free_zcopy) {
  1099. zval_dtor(&zcopy);
  1100. }
  1101. }
  1102. skip_output:
  1103. fmt++;
  1104. }
  1105. odp->nextb = sp;
  1106. return (cc);
  1107. }
  1108. /* }}} */
  1109. /*
  1110. * This is the general purpose conversion function.
  1111. */
  1112. static void strx_printv(int *ccp, char *buf, size_t len, const char *format, va_list ap) /* {{{ */
  1113. {
  1114. buffy od;
  1115. int cc;
  1116. /*
  1117. * First initialize the descriptor
  1118. * Notice that if no length is given, we initialize buf_end to the
  1119. * highest possible address.
  1120. */
  1121. if (len == 0) {
  1122. od.buf_end = (char *) ~0;
  1123. od.nextb = (char *) ~0;
  1124. } else {
  1125. od.buf_end = &buf[len-1];
  1126. od.nextb = buf;
  1127. }
  1128. /*
  1129. * Do the conversion
  1130. */
  1131. cc = format_converter(&od, format, ap);
  1132. if (len != 0 && od.nextb <= od.buf_end) {
  1133. *(od.nextb) = '\0';
  1134. }
  1135. if (ccp) {
  1136. *ccp = cc;
  1137. }
  1138. }
  1139. /* }}} */
  1140. PHPAPI int ap_php_slprintf(char *buf, size_t len, const char *format,...) /* {{{ */
  1141. {
  1142. unsigned int cc;
  1143. va_list ap;
  1144. va_start(ap, format);
  1145. strx_printv(&cc, buf, len, format, ap);
  1146. va_end(ap);
  1147. if (cc >= len) {
  1148. cc = len -1;
  1149. buf[cc] = '\0';
  1150. }
  1151. return cc;
  1152. }
  1153. /* }}} */
  1154. PHPAPI int ap_php_vslprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
  1155. {
  1156. unsigned int cc;
  1157. strx_printv(&cc, buf, len, format, ap);
  1158. if (cc >= len) {
  1159. cc = len -1;
  1160. buf[cc] = '\0';
  1161. }
  1162. return cc;
  1163. }
  1164. /* }}} */
  1165. PHPAPI int ap_php_snprintf(char *buf, size_t len, const char *format,...) /* {{{ */
  1166. {
  1167. int cc;
  1168. va_list ap;
  1169. va_start(ap, format);
  1170. strx_printv(&cc, buf, len, format, ap);
  1171. va_end(ap);
  1172. return (cc);
  1173. }
  1174. /* }}} */
  1175. PHPAPI int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
  1176. {
  1177. int cc;
  1178. strx_printv(&cc, buf, len, format, ap);
  1179. return (cc);
  1180. }
  1181. /* }}} */
  1182. PHPAPI int ap_php_vasprintf(char **buf, const char *format, va_list ap) /* {{{ */
  1183. {
  1184. va_list ap2;
  1185. int cc;
  1186. va_copy(ap2, ap);
  1187. cc = ap_php_vsnprintf(NULL, 0, format, ap2);
  1188. va_end(ap2);
  1189. *buf = NULL;
  1190. if (cc >= 0) {
  1191. if ((*buf = malloc(++cc)) != NULL) {
  1192. if ((cc = ap_php_vsnprintf(*buf, cc, format, ap)) < 0) {
  1193. free(*buf);
  1194. *buf = NULL;
  1195. }
  1196. }
  1197. }
  1198. return cc;
  1199. }
  1200. /* }}} */
  1201. PHPAPI int ap_php_asprintf(char **buf, const char *format, ...) /* {{{ */
  1202. {
  1203. int cc;
  1204. va_list ap;
  1205. va_start(ap, format);
  1206. cc = vasprintf(buf, format, ap);
  1207. va_end(ap);
  1208. return cc;
  1209. }
  1210. /* }}} */
  1211. /*
  1212. * Local variables:
  1213. * tab-width: 4
  1214. * c-basic-offset: 4
  1215. * End:
  1216. * vim600: sw=4 ts=4 fdm=marker
  1217. * vim<600: sw=4 ts=4
  1218. */