diff options
Diffstat (limited to 'main/spprintf.c')
| -rw-r--r-- | main/spprintf.c | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/main/spprintf.c b/main/spprintf.c index d671aa89d9..0af4257cad 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -178,8 +178,10 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) { register char *s = NULL; + register UChar *u = NULL; char *q; int s_len; + int32_t u_len; register int min_width = 0; int precision = 0; @@ -195,6 +197,7 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) char num_buf[NUM_BUF_SIZE]; char char_buf[2]; /* for printing %% and %<unknown> */ + zend_bool free_s; /* free string if allocated here */ /* * Flag variables @@ -207,6 +210,8 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) boolean_e adjust_width; bool_int is_negative; + TSRMLS_FETCH(); + while (*fmt) { if (*fmt != '%') { INS_CHAR(xbuf, *fmt); @@ -218,6 +223,7 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) alternate_form = print_sign = print_blank = NO; pad_char = ' '; prefix_char = NUL; + free_s = 0; fmt++; @@ -511,8 +517,58 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) } break; + case 'v': + if (UG(unicode)) { + goto fmt_unicode; + } else { + goto fmt_string; + } + break; + + case 'R': + { + int type = va_arg(ap, int); + if (type != IS_UNICODE) { + if (alternate_form) { + va_arg(ap, UConverter *); + } + goto fmt_string; + } + } + /* break omitted */ + + case 'r': +fmt_unicode: + { + UConverter *conv = ZEND_U_CONVERTER(UG(output_encoding_conv)); + UErrorCode status = U_ZERO_ERROR; + char *res = NULL; + + if (alternate_form) { + conv = va_arg(ap, UConverter *); + } + + u = va_arg(ap, UChar *); + if (u == NULL) { + s = S_NULL; + s_len = S_NULL_LEN; + break; + } + + u_len = u_strlen(u); + zend_convert_from_unicode(conv, &res, &s_len, u, u_len, &status); + if (U_FAILURE(status)) { + php_error(E_WARNING, "Could not convert Unicode to printable form in s[np]printf call"); + return; + } + s = res; + free_s = 1; + pad_char = ' '; + break; + } case 's': +fmt_string: s = va_arg(ap, char *); if (s != NULL) { s_len = strlen(s); @@ -525,7 +581,6 @@ static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) pad_char = ' '; break; - case 'f': case 'e': case 'E': @@ -705,6 +760,7 @@ fmt_error: * Print the string s. */ INS_STRING(xbuf, s, s_len); + if (free_s) efree(s); if (adjust_width && adjust == LEFT && min_width > s_len) PAD(xbuf, min_width - s_len, pad_char); |
