summaryrefslogtreecommitdiff
path: root/main/spprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/spprintf.c')
-rw-r--r--main/spprintf.c58
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);