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

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

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