File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / formatted_print.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:57 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    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: Stig Sæther Bakken <ssb@php.net>                             |
   16:    +----------------------------------------------------------------------+
   17:  */
   18: 
   19: /* $Id: formatted_print.c,v 1.1.1.4 2014/06/15 20:03:57 misho Exp $ */
   20: 
   21: #include <math.h>				/* modf() */
   22: #include "php.h"
   23: #include "ext/standard/head.h"
   24: #include "php_string.h"
   25: #include "zend_execute.h"
   26: #include <stdio.h>
   27: 
   28: #ifdef HAVE_LOCALE_H
   29: #include <locale.h>
   30: #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
   31: #else
   32: #define LCONV_DECIMAL_POINT '.'
   33: #endif
   34: 
   35: #define ALIGN_LEFT 0
   36: #define ALIGN_RIGHT 1
   37: #define ADJ_WIDTH 1
   38: #define ADJ_PRECISION 2
   39: #define NUM_BUF_SIZE 500
   40: #define FLOAT_PRECISION 6
   41: #define MAX_FLOAT_PRECISION 53
   42: 
   43: #if 0
   44: /* trick to control varargs functions through cpp */
   45: # define PRINTF_DEBUG(arg) php_printf arg
   46: #else
   47: # define PRINTF_DEBUG(arg)
   48: #endif
   49: 
   50: static char hexchars[] = "0123456789abcdef";
   51: static char HEXCHARS[] = "0123456789ABCDEF";
   52: 
   53: /* php_spintf_appendchar() {{{ */
   54: inline static void
   55: php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
   56: {
   57: 	if ((*pos + 1) >= *size) {
   58: 		*size <<= 1;
   59: 		PRINTF_DEBUG(("%s(): ereallocing buffer to %d bytes\n", get_active_function_name(TSRMLS_C), *size));
   60: 		*buffer = erealloc(*buffer, *size);
   61: 	}
   62: 	PRINTF_DEBUG(("sprintf: appending '%c', pos=\n", add, *pos));
   63: 	(*buffer)[(*pos)++] = add;
   64: }
   65: /* }}} */
   66: 
   67: /* php_spintf_appendstring() {{{ */
   68: inline static void
   69: php_sprintf_appendstring(char **buffer, int *pos, int *size, char *add,
   70: 						   int min_width, int max_width, char padding,
   71: 						   int alignment, int len, int neg, int expprec, int always_sign)
   72: {
   73: 	register int npad;
   74: 	int req_size;
   75: 	int copy_len;
   76: 	int m_width;
   77: 
   78: 	copy_len = (expprec ? MIN(max_width, len) : len);
   79: 	npad = min_width - copy_len;
   80: 
   81: 	if (npad < 0) {
   82: 		npad = 0;
   83: 	}
   84: 	
   85: 	PRINTF_DEBUG(("sprintf: appendstring(%x, %d, %d, \"%s\", %d, '%c', %d)\n",
   86: 				  *buffer, *pos, *size, add, min_width, padding, alignment));
   87: 	m_width = MAX(min_width, copy_len);
   88: 
   89: 	if(m_width > INT_MAX - *pos - 1) {
   90: 		zend_error_noreturn(E_ERROR, "Field width %d is too long", m_width);
   91: 	}
   92: 
   93: 	req_size = *pos + m_width + 1;
   94: 
   95: 	if (req_size > *size) {
   96: 		while (req_size > *size) {
   97: 			if(*size > INT_MAX/2) {
   98: 				zend_error_noreturn(E_ERROR, "Field width %d is too long", req_size); 
   99: 			}
  100: 			*size <<= 1;
  101: 		}
  102: 		PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", *size));
  103: 		*buffer = erealloc(*buffer, *size);
  104: 	}
  105: 	if (alignment == ALIGN_RIGHT) {
  106: 		if ((neg || always_sign) && padding=='0') {
  107: 			(*buffer)[(*pos)++] = (neg) ? '-' : '+';
  108: 			add++;
  109: 			len--;
  110: 			copy_len--;
  111: 		}
  112: 		while (npad-- > 0) {
  113: 			(*buffer)[(*pos)++] = padding;
  114: 		}
  115: 	}
  116: 	PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
  117: 	memcpy(&(*buffer)[*pos], add, copy_len + 1);
  118: 	*pos += copy_len;
  119: 	if (alignment == ALIGN_LEFT) {
  120: 		while (npad--) {
  121: 			(*buffer)[(*pos)++] = padding;
  122: 		}
  123: 	}
  124: }
  125: /* }}} */
  126: 
  127: /* php_spintf_appendint() {{{ */
  128: inline static void
  129: php_sprintf_appendint(char **buffer, int *pos, int *size, long number,
  130: 						int width, char padding, int alignment, 
  131: 						int always_sign)
  132: {
  133: 	char numbuf[NUM_BUF_SIZE];
  134: 	register unsigned long magn, nmagn;
  135: 	register unsigned int i = NUM_BUF_SIZE - 1, neg = 0;
  136: 
  137: 	PRINTF_DEBUG(("sprintf: appendint(%x, %x, %x, %d, %d, '%c', %d)\n",
  138: 				  *buffer, pos, size, number, width, padding, alignment));
  139: 	if (number < 0) {
  140: 		neg = 1;
  141: 		magn = ((unsigned long) -(number + 1)) + 1;
  142: 	} else {
  143: 		magn = (unsigned long) number;
  144: 	}
  145: 
  146: 	/* Can't right-pad 0's on integers */
  147: 	if(alignment==0 && padding=='0') padding=' ';
  148: 
  149: 	numbuf[i] = '\0';
  150: 
  151: 	do {
  152: 		nmagn = magn / 10;
  153: 
  154: 		numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
  155: 		magn = nmagn;
  156: 	}
  157: 	while (magn > 0 && i > 0);
  158: 	if (neg) {
  159: 		numbuf[--i] = '-';
  160: 	} else if (always_sign) {
  161: 		numbuf[--i] = '+';
  162: 	}
  163: 	PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n",
  164: 				  number, &numbuf[i], i));
  165: 	php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
  166: 							 padding, alignment, (NUM_BUF_SIZE - 1) - i,
  167: 							 neg, 0, always_sign);
  168: }
  169: /* }}} */
  170: 
  171: /* php_spintf_appenduint() {{{ */
  172: inline static void
  173: php_sprintf_appenduint(char **buffer, int *pos, int *size,
  174: 					   unsigned long number,
  175: 					   int width, char padding, int alignment)
  176: {
  177: 	char numbuf[NUM_BUF_SIZE];
  178: 	register unsigned long magn, nmagn;
  179: 	register unsigned int i = NUM_BUF_SIZE - 1;
  180: 
  181: 	PRINTF_DEBUG(("sprintf: appenduint(%x, %x, %x, %d, %d, '%c', %d)\n",
  182: 				  *buffer, pos, size, number, width, padding, alignment));
  183: 	magn = (unsigned long) number;
  184: 
  185: 	/* Can't right-pad 0's on integers */
  186: 	if (alignment == 0 && padding == '0') padding = ' ';
  187: 
  188: 	numbuf[i] = '\0';
  189: 
  190: 	do {
  191: 		nmagn = magn / 10;
  192: 
  193: 		numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
  194: 		magn = nmagn;
  195: 	} while (magn > 0 && i > 0);
  196: 
  197: 	PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
  198: 	php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
  199: 							 padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
  200: }
  201: /* }}} */
  202: 
  203: /* php_spintf_appenddouble() {{{ */
  204: inline static void
  205: php_sprintf_appenddouble(char **buffer, int *pos,
  206: 						 int *size, double number,
  207: 						 int width, char padding,
  208: 						 int alignment, int precision,
  209: 						 int adjust, char fmt,
  210: 						 int always_sign
  211: 						 TSRMLS_DC)
  212: {
  213: 	char num_buf[NUM_BUF_SIZE];
  214: 	char *s = NULL;
  215: 	int s_len = 0, is_negative = 0;
  216: #ifdef HAVE_LOCALE_H
  217: 	struct lconv *lconv;
  218: #endif
  219: 
  220: 	PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
  221: 				  *buffer, pos, size, number, width, padding, alignment, fmt));
  222: 	if ((adjust & ADJ_PRECISION) == 0) {
  223: 		precision = FLOAT_PRECISION;
  224: 	} else if (precision > MAX_FLOAT_PRECISION) {
  225: 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Requested precision of %d digits was truncated to PHP maximum of %d digits", precision, MAX_FLOAT_PRECISION);
  226: 		precision = MAX_FLOAT_PRECISION;
  227: 	}
  228: 	
  229: 	if (zend_isnan(number)) {
  230: 		is_negative = (number<0);
  231: 		php_sprintf_appendstring(buffer, pos, size, "NaN", 3, 0, padding,
  232: 								 alignment, 3, is_negative, 0, always_sign);
  233: 		return;
  234: 	}
  235: 
  236: 	if (zend_isinf(number)) {
  237: 		is_negative = (number<0);
  238: 		php_sprintf_appendstring(buffer, pos, size, "INF", 3, 0, padding,
  239: 								 alignment, 3, is_negative, 0, always_sign);
  240: 		return;
  241: 	}
  242: 
  243: 	switch (fmt) {			
  244: 		case 'e':
  245: 		case 'E':
  246: 		case 'f':
  247: 		case 'F':
  248: #ifdef HAVE_LOCALE_H
  249: 			lconv = localeconv();
  250: #endif
  251: 			s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
  252: 						(fmt == 'f')?LCONV_DECIMAL_POINT:'.',
  253: 						&is_negative, &num_buf[1], &s_len);
  254: 			if (is_negative) {
  255: 				num_buf[0] = '-';
  256: 				s = num_buf;
  257: 				s_len++;
  258: 			} else if (always_sign) {
  259: 				num_buf[0] = '+';
  260: 				s = num_buf;
  261: 				s_len++;
  262: 			}
  263: 			break;
  264: 
  265: 		case 'g':
  266: 		case 'G':
  267: 			if (precision == 0)
  268: 				precision = 1;
  269: 			/*
  270: 			 * * We use &num_buf[ 1 ], so that we have room for the sign
  271: 			 */
  272: #ifdef HAVE_LOCALE_H
  273: 			lconv = localeconv();
  274: #endif
  275: 			s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
  276: 			is_negative = 0;
  277: 			if (*s == '-') {
  278: 				is_negative = 1;
  279: 				s = &num_buf[1];
  280: 			} else if (always_sign) {
  281: 				num_buf[0] = '+';
  282: 				s = num_buf;
  283: 			}
  284: 
  285: 			s_len = strlen(s);
  286: 			break;
  287: 	}
  288: 
  289: 	php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding,
  290: 							 alignment, s_len, is_negative, 0, always_sign);
  291: }
  292: /* }}} */
  293: 
  294: /* php_spintf_appendd2n() {{{ */
  295: inline static void
  296: php_sprintf_append2n(char **buffer, int *pos, int *size, long number,
  297: 					 int width, char padding, int alignment, int n,
  298: 					 char *chartable, int expprec)
  299: {
  300: 	char numbuf[NUM_BUF_SIZE];
  301: 	register unsigned long num;
  302: 	register unsigned int  i = NUM_BUF_SIZE - 1;
  303: 	register int andbits = (1 << n) - 1;
  304: 
  305: 	PRINTF_DEBUG(("sprintf: append2n(%x, %x, %x, %d, %d, '%c', %d, %d, %x)\n",
  306: 				  *buffer, pos, size, number, width, padding, alignment, n,
  307: 				  chartable));
  308: 	PRINTF_DEBUG(("sprintf: append2n 2^%d andbits=%x\n", n, andbits));
  309: 
  310: 	num = (unsigned long) number;
  311: 	numbuf[i] = '\0';
  312: 
  313: 	do {
  314: 		numbuf[--i] = chartable[(num & andbits)];
  315: 		num >>= n;
  316: 	}
  317: 	while (num > 0);
  318: 
  319: 	php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
  320: 							 padding, alignment, (NUM_BUF_SIZE - 1) - i,
  321: 							 0, expprec, 0);
  322: }
  323: /* }}} */
  324: 
  325: /* php_spintf_getnumber() {{{ */
  326: inline static int
  327: php_sprintf_getnumber(char *buffer, int *pos)
  328: {
  329: 	char *endptr;
  330: 	register long num = strtol(&buffer[*pos], &endptr, 10);
  331: 	register int i = 0;
  332: 
  333: 	if (endptr != NULL) {
  334: 		i = (endptr - &buffer[*pos]);
  335: 	}
  336: 	PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i));
  337: 	*pos += i;
  338: 
  339: 	if (num >= INT_MAX || num < 0) {
  340: 		return -1;
  341: 	} else {
  342: 		return (int) num;
  343: 	}
  344: }
  345: /* }}} */
  346: 
  347: /* php_formatted_print() {{{
  348:  * New sprintf implementation for PHP.
  349:  *
  350:  * Modifiers:
  351:  *
  352:  *  " "   pad integers with spaces
  353:  *  "-"   left adjusted field
  354:  *   n    field size
  355:  *  "."n  precision (floats only)
  356:  *  "+"   Always place a sign (+ or -) in front of a number
  357:  *
  358:  * Type specifiers:
  359:  *
  360:  *  "%"   literal "%", modifiers are ignored.
  361:  *  "b"   integer argument is printed as binary
  362:  *  "c"   integer argument is printed as a single character
  363:  *  "d"   argument is an integer
  364:  *  "f"   the argument is a float
  365:  *  "o"   integer argument is printed as octal
  366:  *  "s"   argument is a string
  367:  *  "x"   integer argument is printed as lowercase hexadecimal
  368:  *  "X"   integer argument is printed as uppercase hexadecimal
  369:  *
  370:  */
  371: static char *
  372: php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC)
  373: {
  374: 	zval ***args, **z_format;
  375: 	int argc, size = 240, inpos = 0, outpos = 0, temppos;
  376: 	int alignment, currarg, adjusting, argnum, width, precision;
  377: 	char *format, *result, padding;
  378: 	int always_sign;
  379: 	int format_len;
  380: 
  381: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
  382: 		return NULL;
  383: 	}
  384: 
  385: 	/* verify the number of args */
  386: 	if ((use_array && argc != (2 + format_offset)) 
  387: 			|| (!use_array && argc < (1 + format_offset))) {
  388: 		efree(args);
  389: 		WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
  390: 	}
  391: 	
  392: 	if (use_array) {
  393: 		int i = 1;
  394: 		zval ***newargs;
  395: 		zval **array;
  396: 
  397: 		z_format = args[format_offset];
  398: 		array = args[1 + format_offset];
  399: 		
  400: 		SEPARATE_ZVAL(array);
  401: 		convert_to_array_ex(array);
  402: 		
  403: 		argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
  404: 		newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
  405: 		newargs[0] = z_format;
  406: 		
  407: 		for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
  408: 			 zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
  409: 			 zend_hash_move_forward(Z_ARRVAL_PP(array)));
  410: 
  411: 		efree(args);
  412: 		args = newargs;
  413: 		format_offset = 0;
  414: 	}
  415: 	
  416: 	convert_to_string_ex(args[format_offset]);
  417: 	format = Z_STRVAL_PP(args[format_offset]);
  418: 	format_len = Z_STRLEN_PP(args[format_offset]);
  419: 	result = emalloc(size);
  420: 
  421: 	currarg = 1;
  422: 
  423: 	while (inpos<format_len) {
  424: 		int expprec = 0, multiuse = 0;
  425: 		zval *tmp;
  426: 
  427: 		PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
  428: 		PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
  429: 		if (format[inpos] != '%') {
  430: 			php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
  431: 		} else if (format[inpos + 1] == '%') {
  432: 			php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
  433: 			inpos += 2;
  434: 		} else {
  435: 			/* starting a new format specifier, reset variables */
  436: 			alignment = ALIGN_RIGHT;
  437: 			adjusting = 0;
  438: 			padding = ' ';
  439: 			always_sign = 0;
  440: 			inpos++;			/* skip the '%' */
  441: 
  442: 			PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
  443: 						  format[inpos], inpos));
  444: 			if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
  445: 				/* first look for argnum */
  446: 				temppos = inpos;
  447: 				while (isdigit((int)format[temppos])) temppos++;
  448: 				if (format[temppos] == '$') {
  449: 					argnum = php_sprintf_getnumber(format, &inpos);
  450: 
  451: 					if (argnum <= 0) {
  452: 						efree(result);
  453: 						efree(args);
  454: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
  455: 						return NULL;
  456: 					}
  457: 
  458: 					multiuse = 1;
  459: 					inpos++;  /* skip the '$' */
  460: 				} else {
  461: 					argnum = currarg++;
  462: 				}
  463: 
  464: 				argnum += format_offset;
  465: 
  466: 				/* after argnum comes modifiers */
  467: 				PRINTF_DEBUG(("sprintf: looking for modifiers\n"
  468: 							  "sprintf: now looking at '%c', inpos=%d\n",
  469: 							  format[inpos], inpos));
  470: 				for (;; inpos++) {
  471: 					if (format[inpos] == ' ' || format[inpos] == '0') {
  472: 						padding = format[inpos];
  473: 					} else if (format[inpos] == '-') {
  474: 						alignment = ALIGN_LEFT;
  475: 						/* space padding, the default */
  476: 					} else if (format[inpos] == '+') {
  477: 						always_sign = 1;
  478: 					} else if (format[inpos] == '\'' && inpos+1<format_len) {
  479: 						padding = format[++inpos];
  480: 					} else {
  481: 						PRINTF_DEBUG(("sprintf: end of modifiers\n"));
  482: 						break;
  483: 					}
  484: 				}
  485: 				PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
  486: 				PRINTF_DEBUG(("sprintf: alignment=%s\n",
  487: 							  (alignment == ALIGN_LEFT) ? "left" : "right"));
  488: 
  489: 
  490: 				/* after modifiers comes width */
  491: 				if (isdigit((int)format[inpos])) {
  492: 					PRINTF_DEBUG(("sprintf: getting width\n"));
  493: 					if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
  494: 						efree(result);
  495: 						efree(args);
  496: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
  497: 						return NULL;
  498: 					}
  499: 					adjusting |= ADJ_WIDTH;
  500: 				} else {
  501: 					width = 0;
  502: 				}
  503: 				PRINTF_DEBUG(("sprintf: width=%d\n", width));
  504: 
  505: 				/* after width and argnum comes precision */
  506: 				if (format[inpos] == '.') {
  507: 					inpos++;
  508: 					PRINTF_DEBUG(("sprintf: getting precision\n"));
  509: 					if (isdigit((int)format[inpos])) {
  510: 						if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
  511: 							efree(result);
  512: 							efree(args);
  513: 							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
  514: 							return NULL;
  515: 						}
  516: 						adjusting |= ADJ_PRECISION;
  517: 						expprec = 1;
  518: 					} else {
  519: 						precision = 0;
  520: 					}
  521: 				} else {
  522: 					precision = 0;
  523: 				}
  524: 				PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
  525: 			} else {
  526: 				width = precision = 0;
  527: 				argnum = currarg++ + format_offset;
  528: 			}
  529: 
  530: 			if (argnum >= argc) {
  531: 				efree(result);
  532: 				efree(args);
  533: 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
  534: 				return NULL;
  535: 			}
  536: 
  537: 			if (format[inpos] == 'l') {
  538: 				inpos++;
  539: 			}
  540: 			PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
  541: 			/* now we expect to find a type specifier */
  542: 			if (multiuse) {
  543: 				MAKE_STD_ZVAL(tmp);
  544: 				*tmp = **(args[argnum]);
  545: 				INIT_PZVAL(tmp);
  546: 				zval_copy_ctor(tmp);
  547: 			} else {
  548: 				SEPARATE_ZVAL(args[argnum]);
  549: 				tmp = *(args[argnum]);
  550: 			}
  551: 
  552: 			switch (format[inpos]) {
  553: 				case 's': {
  554: 					zval *var, var_copy;
  555: 					int use_copy;
  556: 
  557: 					zend_make_printable_zval(tmp, &var_copy, &use_copy);
  558: 					if (use_copy) {
  559: 						var = &var_copy;
  560: 					} else {
  561: 						var = tmp;
  562: 					}
  563: 					php_sprintf_appendstring(&result, &outpos, &size,
  564: 											 Z_STRVAL_P(var),
  565: 											 width, precision, padding,
  566: 											 alignment,
  567: 											 Z_STRLEN_P(var),
  568: 											 0, expprec, 0);
  569: 					if (use_copy) {
  570: 						zval_dtor(&var_copy);
  571: 					}
  572: 					break;
  573: 				}
  574: 
  575: 				case 'd':
  576: 					convert_to_long(tmp);
  577: 					php_sprintf_appendint(&result, &outpos, &size,
  578: 										  Z_LVAL_P(tmp),
  579: 										  width, padding, alignment,
  580: 										  always_sign);
  581: 					break;
  582: 
  583: 				case 'u':
  584: 					convert_to_long(tmp);
  585: 					php_sprintf_appenduint(&result, &outpos, &size,
  586: 										  Z_LVAL_P(tmp),
  587: 										  width, padding, alignment);
  588: 					break;
  589: 
  590: 				case 'g':
  591: 				case 'G':
  592: 				case 'e':
  593: 				case 'E':
  594: 				case 'f':
  595: 				case 'F':
  596: 					convert_to_double(tmp);
  597: 					php_sprintf_appenddouble(&result, &outpos, &size,
  598: 											 Z_DVAL_P(tmp),
  599: 											 width, padding, alignment,
  600: 											 precision, adjusting,
  601: 											 format[inpos], always_sign
  602: 											 TSRMLS_CC);
  603: 					break;
  604: 					
  605: 				case 'c':
  606: 					convert_to_long(tmp);
  607: 					php_sprintf_appendchar(&result, &outpos, &size,
  608: 										(char) Z_LVAL_P(tmp) TSRMLS_CC);
  609: 					break;
  610: 
  611: 				case 'o':
  612: 					convert_to_long(tmp);
  613: 					php_sprintf_append2n(&result, &outpos, &size,
  614: 										 Z_LVAL_P(tmp),
  615: 										 width, padding, alignment, 3,
  616: 										 hexchars, expprec);
  617: 					break;
  618: 
  619: 				case 'x':
  620: 					convert_to_long(tmp);
  621: 					php_sprintf_append2n(&result, &outpos, &size,
  622: 										 Z_LVAL_P(tmp),
  623: 										 width, padding, alignment, 4,
  624: 										 hexchars, expprec);
  625: 					break;
  626: 
  627: 				case 'X':
  628: 					convert_to_long(tmp);
  629: 					php_sprintf_append2n(&result, &outpos, &size,
  630: 										 Z_LVAL_P(tmp),
  631: 										 width, padding, alignment, 4,
  632: 										 HEXCHARS, expprec);
  633: 					break;
  634: 
  635: 				case 'b':
  636: 					convert_to_long(tmp);
  637: 					php_sprintf_append2n(&result, &outpos, &size,
  638: 										 Z_LVAL_P(tmp),
  639: 										 width, padding, alignment, 1,
  640: 										 hexchars, expprec);
  641: 					break;
  642: 
  643: 				case '%':
  644: 					php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
  645: 
  646: 					break;
  647: 				default:
  648: 					break;
  649: 			}
  650: 			if (multiuse) {
  651: 				zval_ptr_dtor(&tmp);
  652: 			}
  653: 			inpos++;
  654: 		}
  655: 	}
  656: 	
  657: 	efree(args);
  658: 	
  659: 	/* possibly, we have to make sure we have room for the terminating null? */
  660: 	result[outpos]=0;
  661: 	*len = outpos;	
  662: 	return result;
  663: }
  664: /* }}} */
  665: 
  666: /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
  667:    Return a formatted string */
  668: PHP_FUNCTION(user_sprintf)
  669: {
  670: 	char *result;
  671: 	int len;
  672: 	
  673: 	if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
  674: 		RETURN_FALSE;
  675: 	}
  676: 	RETVAL_STRINGL(result, len, 0);
  677: }
  678: /* }}} */
  679: 
  680: /* {{{ proto string vsprintf(string format, array args)
  681:    Return a formatted string */
  682: PHP_FUNCTION(vsprintf)
  683: {
  684: 	char *result;
  685: 	int len;
  686: 	
  687: 	if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
  688: 		RETURN_FALSE;
  689: 	}
  690: 	RETVAL_STRINGL(result, len, 0);
  691: }
  692: /* }}} */
  693: 
  694: /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
  695:    Output a formatted string */
  696: PHP_FUNCTION(user_printf)
  697: {
  698: 	char *result;
  699: 	int len, rlen;
  700: 	
  701: 	if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
  702: 		RETURN_FALSE;
  703: 	}
  704: 	rlen = PHPWRITE(result, len);
  705: 	efree(result);
  706: 	RETURN_LONG(rlen);
  707: }
  708: /* }}} */
  709: 
  710: /* {{{ proto int vprintf(string format, array args)
  711:    Output a formatted string */
  712: PHP_FUNCTION(vprintf)
  713: {
  714: 	char *result;
  715: 	int len, rlen;
  716: 	
  717: 	if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
  718: 		RETURN_FALSE;
  719: 	}
  720: 	rlen = PHPWRITE(result, len);
  721: 	efree(result);
  722: 	RETURN_LONG(rlen);
  723: }
  724: /* }}} */
  725: 
  726: /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
  727:    Output a formatted string into a stream */
  728: PHP_FUNCTION(fprintf)
  729: {
  730: 	php_stream *stream;
  731: 	zval *arg1;
  732: 	char *result;
  733: 	int len;
  734: 	
  735: 	if (ZEND_NUM_ARGS() < 2) {
  736: 		WRONG_PARAM_COUNT;
  737: 	}
  738: 	
  739: 	if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
  740: 		RETURN_FALSE;
  741: 	}
  742: 	
  743: 	php_stream_from_zval(stream, &arg1);
  744: 
  745: 	if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) {
  746: 		RETURN_FALSE;
  747: 	}
  748: 
  749: 	php_stream_write(stream, result, len);
  750: 
  751: 	efree(result);
  752: 
  753: 	RETURN_LONG(len);
  754: }
  755: /* }}} */
  756: 
  757: /* {{{ proto int vfprintf(resource stream, string format, array args)
  758:    Output a formatted string into a stream */
  759: PHP_FUNCTION(vfprintf)
  760: {
  761: 	php_stream *stream;
  762: 	zval *arg1;
  763: 	char *result;
  764: 	int len;
  765: 	
  766: 	if (ZEND_NUM_ARGS() != 3) {
  767: 		WRONG_PARAM_COUNT;
  768: 	}
  769: 	
  770: 	if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
  771: 		RETURN_FALSE;
  772: 	}
  773: 	
  774: 	php_stream_from_zval(stream, &arg1);
  775: 
  776: 	if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) {
  777: 		RETURN_FALSE;
  778: 	}
  779: 
  780: 	php_stream_write(stream, result, len);
  781: 
  782: 	efree(result);
  783: 
  784: 	RETURN_LONG(len);
  785: }
  786: /* }}} */
  787: 
  788: /*
  789:  * Local variables:
  790:  * tab-width: 4
  791:  * c-basic-offset: 4
  792:  * End:
  793:  * vim600: sw=4 ts=4 fdm=marker
  794:  * vim<600: sw=4 ts=4
  795:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>