snprintf.c 32 KB

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