24#define LCONV_DECIMAL_POINT (*lconv.decimal_point)
26#define LCONV_DECIMAL_POINT (*lconv->decimal_point)
32#define ADJ_PRECISION 2
33#define NUM_BUF_SIZE 500
34#define FLOAT_PRECISION 6
35#define MAX_FLOAT_PRECISION 53
39# define PRINTF_DEBUG(arg) php_printf arg
41# define PRINTF_DEBUG(arg)
44static const char hexchars[] =
"0123456789abcdef";
45static const char HEXCHARS[] =
"0123456789ABCDEF";
70 }
while ((*
pos +
len) >= nlen);
82 size_t min_width,
size_t max_width,
char padding,
83 size_t alignment,
size_t len,
bool neg,
int expprec,
int always_sign)
90 copy_len = (expprec ?
MIN(max_width,
len) :
len);
91 npad = (min_width < copy_len) ? 0 : min_width - copy_len;
93 PRINTF_DEBUG((
"sprintf: appendstring(%x, %d, %d, \"%s\", %d, '%c', %d)\n",
95 m_width =
MAX(min_width, copy_len);
101 req_size = *
pos + m_width + 1;
105 while (req_size >
size) {
115 if ((neg || always_sign) && padding==
'0') {
139 size_t width,
char padding,
size_t alignment,
146 PRINTF_DEBUG((
"sprintf: appendint(%x, %x, %x, %d, %d, '%c', %d)\n",
156 if(alignment==0 && padding==
'0') padding=
' ';
163 numbuf[--i] = (
unsigned char)(magn - (nmagn * 10)) +
'0';
166 while (magn > 0 && i > 1);
169 }
else if (always_sign) {
172 PRINTF_DEBUG((
"sprintf: appending %d as \"%s\", i=%d\n",
173 number, &numbuf[i], i));
174 php_sprintf_appendstring(
buffer,
pos, &numbuf[i], width, 0,
176 neg, 0, always_sign);
184 size_t width,
char padding,
size_t alignment)
190 PRINTF_DEBUG((
"sprintf: appenduint(%x, %x, %x, %d, %d, '%c', %d)\n",
195 if (alignment == 0 && padding ==
'0') padding =
' ';
202 numbuf[--i] = (
unsigned char)(magn - (nmagn * 10)) +
'0';
204 }
while (magn > 0 && i > 0);
206 PRINTF_DEBUG((
"sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
207 php_sprintf_appendstring(
buffer,
pos, &numbuf[i], width, 0,
208 padding, alignment, (
NUM_BUF_SIZE - 1) - i,
false, 0, 0);
216 size_t width,
char padding,
217 size_t alignment,
int precision,
218 int adjust,
char fmt,
225 bool is_negative =
false;
232 PRINTF_DEBUG((
"sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
242 is_negative = (number<0);
243 php_sprintf_appendstring(
buffer,
pos,
"NaN", 3, 0, padding,
244 alignment, 3, is_negative, 0, always_sign);
249 is_negative = (number<0);
250 char *str = is_negative ?
"-INF" :
"INF";
252 alignment,
strlen(str), is_negative, 0, always_sign);
266 s =
php_conv_fp((fmt ==
'f')?
'F':fmt, number, 0, precision,
268 &is_negative, &num_buf[1], &s_len);
273 }
else if (always_sign) {
288 char decimal_point =
'.';
289 if (fmt ==
'g' || fmt ==
'G') {
298 char exp_char = fmt ==
'G' || fmt ==
'H' ?
'E' :
'e';
300 s =
zend_gcvt(number, precision, decimal_point, exp_char, &num_buf[1]);
305 }
else if (always_sign) {
315 php_sprintf_appendstring(
buffer,
pos,
s, width, 0, padding,
316 alignment, s_len, is_negative, 0, always_sign);
323 size_t width,
char padding,
size_t alignment,
int n,
324 const char *chartable,
int expprec)
329 int andbits = (1 <<
n) - 1;
331 PRINTF_DEBUG((
"sprintf: append2n(%x, %x, %x, %d, %d, '%c', %d, %d, %x)\n",
334 PRINTF_DEBUG((
"sprintf: append2n 2^%d andbits=%x\n",
n, andbits));
340 numbuf[--i] = chartable[(num & andbits)];
345 php_sprintf_appendstring(
buffer,
pos, &numbuf[i], width, 0,
353php_sprintf_getnumber(
char **
buffer,
size_t *
len)
364 PRINTF_DEBUG((
"sprintf_getnumber: number was %d bytes long\n", i));
366 if (num >=
INT_MAX || num < 0) {
374#define ARG_NUM_NEXT -1
375#define ARG_NUM_INVALID -2
378 char *temppos = *format;
379 while (isdigit((
int) *temppos)) temppos++;
380 if (*temppos !=
'$') {
384 int argnum = php_sprintf_getnumber(format, format_len);
423php_formatted_print(
char *format,
size_t format_len,
zval *
args,
int argc,
int nb_additional_parameters)
425 size_t size = 240, outpos = 0;
426 int alignment, currarg, adjusting, argnum, width, precision;
427 char *temppos, padding;
430 int max_missing_argnum = -1;
441 temppos = memchr(format,
'%', format_len);
443 php_sprintf_appendchars(&
result, &outpos, format, format_len);
445 }
else if (temppos != format) {
446 php_sprintf_appendchars(&
result, &outpos, format, temppos - format);
447 format_len -= temppos - format;
453 if (*format ==
'%') {
454 php_sprintf_appendchar(&
result, &outpos,
'%');
465 PRINTF_DEBUG((
"sprintf: first looking at '%c', inpos=%d\n",
467 if (isalpha((
int)*format)) {
468 width = precision = 0;
479 "sprintf: now looking at '%c', inpos=%d\n",
481 for (;; format++, format_len--) {
482 if (*format ==
' ' || *format ==
'0') {
484 }
else if (*format ==
'-') {
487 }
else if (*format ==
'+') {
489 }
else if (*format ==
'\'') {
490 if (format_len > 1) {
505 (alignment ==
ALIGN_LEFT) ?
"left" :
"right"));
509 if (*format ==
'*') {
518 width_argnum = currarg++;
520 if (width_argnum >= argc) {
521 max_missing_argnum =
MAX(max_missing_argnum, width_argnum);
524 tmp = &
args[width_argnum];
536 }
else if (isdigit((
int)*format)) {
538 if ((width = php_sprintf_getnumber(&format, &format_len)) < 0) {
549 if (*format ==
'.') {
553 if (*format ==
'*') {
562 prec_argnum = currarg++;
564 if (prec_argnum >= argc) {
565 max_missing_argnum =
MAX(max_missing_argnum, prec_argnum);
568 tmp = &
args[prec_argnum];
581 }
else if (isdigit((
int)*format)) {
582 if ((precision = php_sprintf_getnumber(&format, &format_len)) < 0) {
597 if (*format ==
'l') {
601 PRINTF_DEBUG((
"sprintf: format character='%c'\n", *format));
606 if (argnum >= argc) {
607 max_missing_argnum =
MAX(max_missing_argnum, argnum);
611 if (expprec && precision == -1
612 && *format !=
'g' && *format !=
'G' && *format !=
'h' && *format !=
'H') {
613 zend_value_error(
"Precision -1 is only supported for %%g, %%G, %%h and %%H");
623 php_sprintf_appendstring(&
result, &outpos,
625 width, precision, padding,
629 zend_tmp_string_release(t);
634 php_sprintf_appendint(&
result, &outpos,
636 width, padding, alignment,
641 php_sprintf_appenduint(&
result, &outpos,
643 width, padding, alignment);
654 php_sprintf_appenddouble(&
result, &outpos,
655 zval_get_double(tmp),
656 width, padding, alignment,
657 precision, adjusting,
663 php_sprintf_appendchar(&
result, &outpos,
664 (
char) zval_get_long(tmp));
668 php_sprintf_append2n(&
result, &outpos,
670 width, padding, alignment, 3,
675 php_sprintf_append2n(&
result, &outpos,
677 width, padding, alignment, 4,
682 php_sprintf_append2n(&
result, &outpos,
684 width, padding, alignment, 4,
689 php_sprintf_append2n(&
result, &outpos,
691 width, padding, alignment, 1,
696 php_sprintf_appendchar(&
result, &outpos,
'%');
716 if (max_missing_argnum >= 0) {
717 if (nb_additional_parameters == -1) {
718 zend_value_error(
"The arguments array must contain %d items, %d given", max_missing_argnum + 1, argc);
720 zend_argument_count_error(
"%d arguments are required, %d given", max_missing_argnum + nb_additional_parameters + 1, argc + nb_additional_parameters);
731 zend_string_efree(
result);
737static zval *php_formatted_print_get_array(
zend_array *array,
int *argc)
742 n = zend_hash_num_elements(array);
769 result = php_formatted_print(format, format_len,
args, argc, 1);
792 args = php_formatted_print_get_array(array, &argc);
794 result = php_formatted_print(format, format_len,
args, argc, -1);
818 result = php_formatted_print(format, format_len,
args, argc, 1);
823 zend_string_efree(
result);
844 args = php_formatted_print_get_array(array, &argc);
846 result = php_formatted_print(format, format_len,
args, argc, -1);
852 zend_string_efree(
result);
875 result = php_formatted_print(format, format_len,
args, argc, 2);
883 zend_string_efree(
result);
906 args = php_formatted_print_get_array(array, &argc);
908 result = php_formatted_print(format, format_len,
args, argc, -1);
917 zend_string_efree(
result);
vprintf(string $format, array $values)
fprintf($stream, string $format, mixed ... $values)
printf(string $format, mixed ... $values)
vfprintf($stream, string $format, array $values)
vsprintf(string $format, array $values)
sprintf("0x%X", $numelems)
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
unsigned const char * pos
#define PHPWRITE(str, str_len)
struct _php_stream php_stream
#define php_stream_from_zval(xstr, pzval)
#define php_stream_write(stream, buf, count)
PHPAPI struct lconv * localeconv_r(struct lconv *out)
#define LCONV_DECIMAL_POINT
PHPAPI char * php_conv_fp(char format, double num, bool add_dp, int precision, char dec_point, bool *is_negative, char *buf, size_t *len)
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
ZEND_API ZEND_COLD void zend_argument_count_error(const char *format,...)
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
#define ZEND_PARSE_PARAMETERS_END()
#define Z_PARAM_RESOURCE(dest)
#define Z_PARAM_STRING(dest, dest_len)
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
#define Z_PARAM_VARIADIC(spec, dest, dest_num)
#define Z_PARAM_ARRAY_HT(dest)
#define safe_emalloc(nmemb, size, offset)
ZEND_API const char * get_active_function_name(void)
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_VAL(ht, _val)
#define ZEND_STRTOL(s0, s1, base)
struct _zend_string zend_string
struct _zend_array zend_array
ZEND_API char * zend_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf)
#define Z_STRVAL_P(zval_p)
#define ZVAL_COPY_VALUE(z, v)