Annotation of embedaddon/php/ext/standard/formatted_print.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 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: 
1.1.1.2 ! misho      19: /* $Id$ */
1.1       misho      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: 
                    380:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
                    381:                return NULL;
                    382:        }
                    383: 
                    384:        /* verify the number of args */
                    385:        if ((use_array && argc != (2 + format_offset)) 
                    386:                        || (!use_array && argc < (1 + format_offset))) {
                    387:                efree(args);
                    388:                WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
                    389:        }
                    390:        
                    391:        if (use_array) {
                    392:                int i = 1;
                    393:                zval ***newargs;
                    394:                zval **array;
                    395: 
                    396:                z_format = args[format_offset];
                    397:                array = args[1 + format_offset];
                    398:                
                    399:                SEPARATE_ZVAL(array);
                    400:                convert_to_array_ex(array);
                    401:                
                    402:                argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
                    403:                newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
                    404:                newargs[0] = z_format;
                    405:                
                    406:                for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
                    407:                         zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
                    408:                         zend_hash_move_forward(Z_ARRVAL_PP(array)));
                    409: 
                    410:                efree(args);
                    411:                args = newargs;
                    412:                format_offset = 0;
                    413:        }
                    414:        
                    415:        convert_to_string_ex(args[format_offset]);
                    416:        format = Z_STRVAL_PP(args[format_offset]);
                    417:        result = emalloc(size);
                    418: 
                    419:        currarg = 1;
                    420: 
                    421:        while (inpos<Z_STRLEN_PP(args[format_offset])) {
                    422:                int expprec = 0, multiuse = 0;
                    423:                zval *tmp;
                    424: 
                    425:                PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
                    426:                PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
                    427:                if (format[inpos] != '%') {
                    428:                        php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
                    429:                } else if (format[inpos + 1] == '%') {
                    430:                        php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
                    431:                        inpos += 2;
                    432:                } else {
                    433:                        /* starting a new format specifier, reset variables */
                    434:                        alignment = ALIGN_RIGHT;
                    435:                        adjusting = 0;
                    436:                        padding = ' ';
                    437:                        always_sign = 0;
                    438:                        inpos++;                        /* skip the '%' */
                    439: 
                    440:                        PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
                    441:                                                  format[inpos], inpos));
                    442:                        if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
                    443:                                /* first look for argnum */
                    444:                                temppos = inpos;
                    445:                                while (isdigit((int)format[temppos])) temppos++;
                    446:                                if (format[temppos] == '$') {
                    447:                                        argnum = php_sprintf_getnumber(format, &inpos);
                    448: 
                    449:                                        if (argnum <= 0) {
                    450:                                                efree(result);
                    451:                                                efree(args);
                    452:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
                    453:                                                return NULL;
                    454:                                        }
                    455: 
                    456:                                        multiuse = 1;
                    457:                                        inpos++;  /* skip the '$' */
                    458:                                } else {
                    459:                                        argnum = currarg++;
                    460:                                }
                    461: 
                    462:                                argnum += format_offset;
                    463: 
                    464:                                /* after argnum comes modifiers */
                    465:                                PRINTF_DEBUG(("sprintf: looking for modifiers\n"
                    466:                                                          "sprintf: now looking at '%c', inpos=%d\n",
                    467:                                                          format[inpos], inpos));
                    468:                                for (;; inpos++) {
                    469:                                        if (format[inpos] == ' ' || format[inpos] == '0') {
                    470:                                                padding = format[inpos];
                    471:                                        } else if (format[inpos] == '-') {
                    472:                                                alignment = ALIGN_LEFT;
                    473:                                                /* space padding, the default */
                    474:                                        } else if (format[inpos] == '+') {
                    475:                                                always_sign = 1;
                    476:                                        } else if (format[inpos] == '\'') {
                    477:                                                padding = format[++inpos];
                    478:                                        } else {
                    479:                                                PRINTF_DEBUG(("sprintf: end of modifiers\n"));
                    480:                                                break;
                    481:                                        }
                    482:                                }
                    483:                                PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
                    484:                                PRINTF_DEBUG(("sprintf: alignment=%s\n",
                    485:                                                          (alignment == ALIGN_LEFT) ? "left" : "right"));
                    486: 
                    487: 
                    488:                                /* after modifiers comes width */
                    489:                                if (isdigit((int)format[inpos])) {
                    490:                                        PRINTF_DEBUG(("sprintf: getting width\n"));
                    491:                                        if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
                    492:                                                efree(result);
                    493:                                                efree(args);
                    494:                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
                    495:                                                return NULL;
                    496:                                        }
                    497:                                        adjusting |= ADJ_WIDTH;
                    498:                                } else {
                    499:                                        width = 0;
                    500:                                }
                    501:                                PRINTF_DEBUG(("sprintf: width=%d\n", width));
                    502: 
                    503:                                /* after width and argnum comes precision */
                    504:                                if (format[inpos] == '.') {
                    505:                                        inpos++;
                    506:                                        PRINTF_DEBUG(("sprintf: getting precision\n"));
                    507:                                        if (isdigit((int)format[inpos])) {
                    508:                                                if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
                    509:                                                        efree(result);
                    510:                                                        efree(args);
                    511:                                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
                    512:                                                        return NULL;
                    513:                                                }
                    514:                                                adjusting |= ADJ_PRECISION;
                    515:                                                expprec = 1;
                    516:                                        } else {
                    517:                                                precision = 0;
                    518:                                        }
                    519:                                } else {
                    520:                                        precision = 0;
                    521:                                }
                    522:                                PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
                    523:                        } else {
                    524:                                width = precision = 0;
                    525:                                argnum = currarg++ + format_offset;
                    526:                        }
                    527: 
                    528:                        if (argnum >= argc) {
                    529:                                efree(result);
                    530:                                efree(args);
                    531:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
                    532:                                return NULL;
                    533:                        }
                    534: 
                    535:                        if (format[inpos] == 'l') {
                    536:                                inpos++;
                    537:                        }
                    538:                        PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
                    539:                        /* now we expect to find a type specifier */
                    540:                        if (multiuse) {
                    541:                                MAKE_STD_ZVAL(tmp);
                    542:                                *tmp = **(args[argnum]);
                    543:                                INIT_PZVAL(tmp);
                    544:                                zval_copy_ctor(tmp);
                    545:                        } else {
                    546:                                SEPARATE_ZVAL(args[argnum]);
                    547:                                tmp = *(args[argnum]);
                    548:                        }
                    549: 
                    550:                        switch (format[inpos]) {
                    551:                                case 's': {
                    552:                                        zval *var, var_copy;
                    553:                                        int use_copy;
                    554: 
                    555:                                        zend_make_printable_zval(tmp, &var_copy, &use_copy);
                    556:                                        if (use_copy) {
                    557:                                                var = &var_copy;
                    558:                                        } else {
                    559:                                                var = tmp;
                    560:                                        }
                    561:                                        php_sprintf_appendstring(&result, &outpos, &size,
                    562:                                                                                         Z_STRVAL_P(var),
                    563:                                                                                         width, precision, padding,
                    564:                                                                                         alignment,
                    565:                                                                                         Z_STRLEN_P(var),
                    566:                                                                                         0, expprec, 0);
                    567:                                        if (use_copy) {
                    568:                                                zval_dtor(&var_copy);
                    569:                                        }
                    570:                                        break;
                    571:                                }
                    572: 
                    573:                                case 'd':
                    574:                                        convert_to_long(tmp);
                    575:                                        php_sprintf_appendint(&result, &outpos, &size,
                    576:                                                                                  Z_LVAL_P(tmp),
                    577:                                                                                  width, padding, alignment,
                    578:                                                                                  always_sign);
                    579:                                        break;
                    580: 
                    581:                                case 'u':
                    582:                                        convert_to_long(tmp);
                    583:                                        php_sprintf_appenduint(&result, &outpos, &size,
                    584:                                                                                  Z_LVAL_P(tmp),
                    585:                                                                                  width, padding, alignment);
                    586:                                        break;
                    587: 
                    588:                                case 'g':
                    589:                                case 'G':
                    590:                                case 'e':
                    591:                                case 'E':
                    592:                                case 'f':
                    593:                                case 'F':
                    594:                                        convert_to_double(tmp);
                    595:                                        php_sprintf_appenddouble(&result, &outpos, &size,
                    596:                                                                                         Z_DVAL_P(tmp),
                    597:                                                                                         width, padding, alignment,
                    598:                                                                                         precision, adjusting,
                    599:                                                                                         format[inpos], always_sign
                    600:                                                                                         TSRMLS_CC);
                    601:                                        break;
                    602:                                        
                    603:                                case 'c':
                    604:                                        convert_to_long(tmp);
                    605:                                        php_sprintf_appendchar(&result, &outpos, &size,
                    606:                                                                                (char) Z_LVAL_P(tmp) TSRMLS_CC);
                    607:                                        break;
                    608: 
                    609:                                case 'o':
                    610:                                        convert_to_long(tmp);
                    611:                                        php_sprintf_append2n(&result, &outpos, &size,
                    612:                                                                                 Z_LVAL_P(tmp),
                    613:                                                                                 width, padding, alignment, 3,
                    614:                                                                                 hexchars, expprec);
                    615:                                        break;
                    616: 
                    617:                                case 'x':
                    618:                                        convert_to_long(tmp);
                    619:                                        php_sprintf_append2n(&result, &outpos, &size,
                    620:                                                                                 Z_LVAL_P(tmp),
                    621:                                                                                 width, padding, alignment, 4,
                    622:                                                                                 hexchars, expprec);
                    623:                                        break;
                    624: 
                    625:                                case 'X':
                    626:                                        convert_to_long(tmp);
                    627:                                        php_sprintf_append2n(&result, &outpos, &size,
                    628:                                                                                 Z_LVAL_P(tmp),
                    629:                                                                                 width, padding, alignment, 4,
                    630:                                                                                 HEXCHARS, expprec);
                    631:                                        break;
                    632: 
                    633:                                case 'b':
                    634:                                        convert_to_long(tmp);
                    635:                                        php_sprintf_append2n(&result, &outpos, &size,
                    636:                                                                                 Z_LVAL_P(tmp),
                    637:                                                                                 width, padding, alignment, 1,
                    638:                                                                                 hexchars, expprec);
                    639:                                        break;
                    640: 
                    641:                                case '%':
                    642:                                        php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
                    643: 
                    644:                                        break;
                    645:                                default:
                    646:                                        break;
                    647:                        }
                    648:                        if (multiuse) {
                    649:                                zval_ptr_dtor(&tmp);
                    650:                        }
                    651:                        inpos++;
                    652:                }
                    653:        }
                    654:        
                    655:        efree(args);
                    656:        
                    657:        /* possibly, we have to make sure we have room for the terminating null? */
                    658:        result[outpos]=0;
                    659:        *len = outpos;  
                    660:        return result;
                    661: }
                    662: /* }}} */
                    663: 
                    664: /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
                    665:    Return a formatted string */
                    666: PHP_FUNCTION(user_sprintf)
                    667: {
                    668:        char *result;
                    669:        int len;
                    670:        
                    671:        if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
                    672:                RETURN_FALSE;
                    673:        }
                    674:        RETVAL_STRINGL(result, len, 0);
                    675: }
                    676: /* }}} */
                    677: 
                    678: /* {{{ proto string vsprintf(string format, array args)
                    679:    Return a formatted string */
                    680: PHP_FUNCTION(vsprintf)
                    681: {
                    682:        char *result;
                    683:        int len;
                    684:        
                    685:        if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
                    686:                RETURN_FALSE;
                    687:        }
                    688:        RETVAL_STRINGL(result, len, 0);
                    689: }
                    690: /* }}} */
                    691: 
                    692: /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
                    693:    Output a formatted string */
                    694: PHP_FUNCTION(user_printf)
                    695: {
                    696:        char *result;
                    697:        int len, rlen;
                    698:        
                    699:        if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
                    700:                RETURN_FALSE;
                    701:        }
                    702:        rlen = PHPWRITE(result, len);
                    703:        efree(result);
                    704:        RETURN_LONG(rlen);
                    705: }
                    706: /* }}} */
                    707: 
                    708: /* {{{ proto int vprintf(string format, array args)
                    709:    Output a formatted string */
                    710: PHP_FUNCTION(vprintf)
                    711: {
                    712:        char *result;
                    713:        int len, rlen;
                    714:        
                    715:        if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
                    716:                RETURN_FALSE;
                    717:        }
                    718:        rlen = PHPWRITE(result, len);
                    719:        efree(result);
                    720:        RETURN_LONG(rlen);
                    721: }
                    722: /* }}} */
                    723: 
                    724: /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
                    725:    Output a formatted string into a stream */
                    726: PHP_FUNCTION(fprintf)
                    727: {
                    728:        php_stream *stream;
                    729:        zval *arg1;
                    730:        char *result;
                    731:        int len;
                    732:        
                    733:        if (ZEND_NUM_ARGS() < 2) {
                    734:                WRONG_PARAM_COUNT;
                    735:        }
                    736:        
                    737:        if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
                    738:                RETURN_FALSE;
                    739:        }
                    740:        
                    741:        php_stream_from_zval(stream, &arg1);
                    742: 
                    743:        if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) {
                    744:                RETURN_FALSE;
                    745:        }
                    746: 
                    747:        php_stream_write(stream, result, len);
                    748: 
                    749:        efree(result);
                    750: 
                    751:        RETURN_LONG(len);
                    752: }
                    753: /* }}} */
                    754: 
                    755: /* {{{ proto int vfprintf(resource stream, string format, array args)
                    756:    Output a formatted string into a stream */
                    757: PHP_FUNCTION(vfprintf)
                    758: {
                    759:        php_stream *stream;
                    760:        zval *arg1;
                    761:        char *result;
                    762:        int len;
                    763:        
                    764:        if (ZEND_NUM_ARGS() != 3) {
                    765:                WRONG_PARAM_COUNT;
                    766:        }
                    767:        
                    768:        if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
                    769:                RETURN_FALSE;
                    770:        }
                    771:        
                    772:        php_stream_from_zval(stream, &arg1);
                    773: 
                    774:        if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) {
                    775:                RETURN_FALSE;
                    776:        }
                    777: 
                    778:        php_stream_write(stream, result, len);
                    779: 
                    780:        efree(result);
                    781: 
                    782:        RETURN_LONG(len);
                    783: }
                    784: /* }}} */
                    785: 
                    786: /*
                    787:  * Local variables:
                    788:  * tab-width: 4
                    789:  * c-basic-offset: 4
                    790:  * End:
                    791:  * vim600: sw=4 ts=4 fdm=marker
                    792:  * vim<600: sw=4 ts=4
                    793:  */

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