Annotation of embedaddon/php/main/spprintf.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: Marcus Boerger <helly@php.net>                               |
        !            16:    +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* $Id: spprintf.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: /* This is the spprintf implementation.
        !            22:  * It has emerged from apache snprintf. See original header:
        !            23:  */
        !            24: 
        !            25: /* ====================================================================
        !            26:  * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
        !            27:  *
        !            28:  * Redistribution and use in source and binary forms, with or without
        !            29:  * modification, are permitted provided that the following conditions
        !            30:  * are met:
        !            31:  *
        !            32:  * 1. Redistributions of source code must retain the above copyright
        !            33:  *    notice, this list of conditions and the following disclaimer.
        !            34:  *
        !            35:  * 2. Redistributions in binary form must reproduce the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer in
        !            37:  *    the documentation and/or other materials provided with the
        !            38:  *    distribution.
        !            39:  *
        !            40:  * 3. All advertising materials mentioning features or use of this
        !            41:  *    software must display the following acknowledgment:
        !            42:  *    "This product includes software developed by the Apache Group
        !            43:  *    for use in the Apache HTTP server project (http://www.apache.org/)."
        !            44:  *
        !            45:  * 4. The names "Apache Server" and "Apache Group" must not be used to
        !            46:  *    endorse or promote products derived from this software without
        !            47:  *    prior written permission.
        !            48:  *
        !            49:  * 5. Redistributions of any form whatsoever must retain the following
        !            50:  *    acknowledgment:
        !            51:  *    "This product includes software developed by the Apache Group
        !            52:  *    for use in the Apache HTTP server project (http://www.apache.org/)."
        !            53:  *
        !            54:  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
        !            55:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            56:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            57:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
        !            58:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            59:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            60:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        !            61:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            63:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            64:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
        !            65:  * OF THE POSSIBILITY OF SUCH DAMAGE.
        !            66:  * ====================================================================
        !            67:  *
        !            68:  * This software consists of voluntary contributions made by many
        !            69:  * individuals on behalf of the Apache Group and was originally based
        !            70:  * on public domain software written at the National Center for
        !            71:  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
        !            72:  * For more information on the Apache Group and the Apache HTTP server
        !            73:  * project, please see <http://www.apache.org/>.
        !            74:  *
        !            75:  * This code is based on, and used with the permission of, the
        !            76:  * SIO stdio-replacement strx_* functions by Panos Tsirigotis
        !            77:  * <panos@alumni.cs.colorado.edu> for xinetd.
        !            78:  */
        !            79: #define _GNU_SOURCE
        !            80: #include "php.h"
        !            81: 
        !            82: #include <stddef.h>
        !            83: #include <stdio.h>
        !            84: #include <ctype.h>
        !            85: #include <sys/types.h>
        !            86: #include <stdarg.h>
        !            87: #include <string.h>
        !            88: #include <stdlib.h>
        !            89: #include <math.h>
        !            90: #ifdef HAVE_INTTYPES_H
        !            91: #include <inttypes.h>
        !            92: #endif
        !            93: 
        !            94: #ifdef HAVE_LOCALE_H
        !            95: #include <locale.h>
        !            96: #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
        !            97: #else
        !            98: #define LCONV_DECIMAL_POINT '.'
        !            99: #endif
        !           100: 
        !           101: #include "snprintf.h"
        !           102: 
        !           103: #define FALSE           0
        !           104: #define TRUE            1
        !           105: #define NUL             '\0'
        !           106: #define INT_NULL        ((int *)0)
        !           107: 
        !           108: #define S_NULL          "(null)"
        !           109: #define S_NULL_LEN      6
        !           110: 
        !           111: #define FLOAT_DIGITS    6
        !           112: #define EXPONENT_LENGTH 10
        !           113: 
        !           114: #include "ext/standard/php_smart_str.h"
        !           115: 
        !           116: /* {{{ macros */
        !           117: 
        !           118: /*
        !           119:  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
        !           120:  *
        !           121:  * XXX: this is a magic number; do not decrease it
        !           122:  * Emax = 1023
        !           123:  * NDIG = 320
        !           124:  * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
        !           125:  */
        !           126: #define NUM_BUF_SIZE    2048
        !           127: 
        !           128: /*
        !           129:  * The INS_CHAR macro inserts a character in the buffer.
        !           130:  *
        !           131:  * NOTE: Evaluation of the ch argument should not have any side-effects
        !           132:  */
        !           133: #define INS_CHAR_NR(xbuf, ch) do {     \
        !           134:        smart_str_appendc(xbuf, ch);    \
        !           135: } while (0)
        !           136: 
        !           137: #define INS_STRING(xbuf, s, slen) do {         \
        !           138:        smart_str_appendl(xbuf, s, slen);       \
        !           139: } while (0)
        !           140: 
        !           141: #define INS_CHAR(xbuf, ch)          \
        !           142:        INS_CHAR_NR(xbuf, ch)
        !           143: 
        !           144: /*
        !           145:  * Macro that does padding. The padding is done by printing
        !           146:  * the character ch.
        !           147:  */
        !           148: #define PAD(xbuf, count, ch) do {                                      \
        !           149:        if ((count) > 0) {                                      \
        !           150:                size_t newlen;                                                          \
        !           151:                smart_str_alloc(xbuf, (count), 0);                      \
        !           152:                memset(xbuf->c + xbuf->len, ch, (count));       \
        !           153:                xbuf->len += (count);                           \
        !           154:        }                                                                                               \
        !           155: } while (0)
        !           156: 
        !           157: #define NUM(c) (c - '0')
        !           158: 
        !           159: #define STR_TO_DEC(str, num) do {                      \
        !           160:        num = NUM(*str++);                      \
        !           161:        while (isdigit((int)*str)) {            \
        !           162:                num *= 10;                              \
        !           163:                num += NUM(*str++);                     \
        !           164:                if (num >= INT_MAX / 10) {                      \
        !           165:                        while (isdigit((int)*str++));   \
        !           166:                        break;                                                  \
        !           167:                }                                                                       \
        !           168:     }                                                                          \
        !           169: } while (0)
        !           170: 
        !           171: /*
        !           172:  * This macro does zero padding so that the precision
        !           173:  * requirement is satisfied. The padding is done by
        !           174:  * adding '0's to the left of the string that is going
        !           175:  * to be printed.
        !           176:  */
        !           177: #define FIX_PRECISION(adjust, precision, s, s_len) do {        \
        !           178:     if (adjust)                                                                \
        !           179:                while (s_len < precision) {                     \
        !           180:                        *--s = '0';                                     \
        !           181:                        s_len++;                                        \
        !           182:                }                                                                                               \
        !           183: } while (0)
        !           184: 
        !           185: /* }}} */
        !           186: 
        !           187: 
        !           188: #if !HAVE_STRNLEN
        !           189: static size_t strnlen(const char *s, size_t maxlen) {
        !           190:        char *r = memchr(s, '\0', maxlen);
        !           191:        return r ? r-s : maxlen;
        !           192: }
        !           193: #endif
        !           194: 
        !           195: /*
        !           196:  * Do format conversion placing the output in buffer
        !           197:  */
        !           198: static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) /* {{{ */
        !           199: {
        !           200:        char *s = NULL;
        !           201:        int s_len, free_zcopy;
        !           202:        zval *zvp, zcopy;
        !           203: 
        !           204:        int min_width = 0;
        !           205:        int precision = 0;
        !           206:        enum {
        !           207:                LEFT, RIGHT
        !           208:        } adjust;
        !           209:        char pad_char;
        !           210:        char prefix_char;
        !           211: 
        !           212:        double fp_num;
        !           213:        wide_int i_num = (wide_int) 0;
        !           214:        u_wide_int ui_num;
        !           215: 
        !           216:        char num_buf[NUM_BUF_SIZE];
        !           217:        char char_buf[2];                       /* for printing %% and %<unknown> */
        !           218: 
        !           219: #ifdef HAVE_LOCALE_H
        !           220:        struct lconv *lconv = NULL;
        !           221: #endif
        !           222: 
        !           223:        /*
        !           224:         * Flag variables
        !           225:         */
        !           226:        length_modifier_e modifier;
        !           227:        boolean_e alternate_form;
        !           228:        boolean_e print_sign;
        !           229:        boolean_e print_blank;
        !           230:        boolean_e adjust_precision;
        !           231:        boolean_e adjust_width;
        !           232:        bool_int is_negative;
        !           233: 
        !           234:        while (*fmt) {
        !           235:                if (*fmt != '%') {
        !           236:                        INS_CHAR(xbuf, *fmt);
        !           237:                } else {
        !           238:                        /*
        !           239:                         * Default variable settings
        !           240:                         */
        !           241:                        adjust = RIGHT;
        !           242:                        alternate_form = print_sign = print_blank = NO;
        !           243:                        pad_char = ' ';
        !           244:                        prefix_char = NUL;
        !           245:                        free_zcopy = 0;
        !           246: 
        !           247:                        fmt++;
        !           248: 
        !           249:                        /*
        !           250:                         * Try to avoid checking for flags, width or precision
        !           251:                         */
        !           252:                        if (isascii((int)*fmt) && !islower((int)*fmt)) {
        !           253:                                /*
        !           254:                                 * Recognize flags: -, #, BLANK, +
        !           255:                                 */
        !           256:                                for (;; fmt++) {
        !           257:                                        if (*fmt == '-')
        !           258:                                                adjust = LEFT;
        !           259:                                        else if (*fmt == '+')
        !           260:                                                print_sign = YES;
        !           261:                                        else if (*fmt == '#')
        !           262:                                                alternate_form = YES;
        !           263:                                        else if (*fmt == ' ')
        !           264:                                                print_blank = YES;
        !           265:                                        else if (*fmt == '0')
        !           266:                                                pad_char = '0';
        !           267:                                        else
        !           268:                                                break;
        !           269:                                }
        !           270: 
        !           271:                                /*
        !           272:                                 * Check if a width was specified
        !           273:                                 */
        !           274:                                if (isdigit((int)*fmt)) {
        !           275:                                        STR_TO_DEC(fmt, min_width);
        !           276:                                        adjust_width = YES;
        !           277:                                } else if (*fmt == '*') {
        !           278:                                        min_width = va_arg(ap, int);
        !           279:                                        fmt++;
        !           280:                                        adjust_width = YES;
        !           281:                                        if (min_width < 0) {
        !           282:                                                adjust = LEFT;
        !           283:                                                min_width = -min_width;
        !           284:                                        }
        !           285:                                } else
        !           286:                                        adjust_width = NO;
        !           287: 
        !           288:                                /*
        !           289:                                 * Check if a precision was specified
        !           290:                                 */
        !           291:                                if (*fmt == '.') {
        !           292:                                        adjust_precision = YES;
        !           293:                                        fmt++;
        !           294:                                        if (isdigit((int)*fmt)) {
        !           295:                                                STR_TO_DEC(fmt, precision);
        !           296:                                        } else if (*fmt == '*') {
        !           297:                                                precision = va_arg(ap, int);
        !           298:                                                fmt++;
        !           299:                                                if (precision < 0)
        !           300:                                                        precision = 0;
        !           301:                                        } else
        !           302:                                                precision = 0;
        !           303:                                        
        !           304:                                        if (precision > FORMAT_CONV_MAX_PRECISION) {
        !           305:                                                precision = FORMAT_CONV_MAX_PRECISION;
        !           306:                                        }
        !           307:                                } else
        !           308:                                        adjust_precision = NO;
        !           309:                        } else
        !           310:                                adjust_precision = adjust_width = NO;
        !           311: 
        !           312:                        /*
        !           313:                         * Modifier check
        !           314:                         */
        !           315:                        switch (*fmt) {
        !           316:                                case 'L':
        !           317:                                        fmt++;
        !           318:                                        modifier = LM_LONG_DOUBLE;
        !           319:                                        break;
        !           320:                                case 'I':
        !           321:                                        fmt++;
        !           322: #if SIZEOF_LONG_LONG
        !           323:                                        if (*fmt == '6' && *(fmt+1) == '4') {
        !           324:                                                fmt += 2;
        !           325:                                                modifier = LM_LONG_LONG;
        !           326:                                        } else
        !           327: #endif
        !           328:                                                if (*fmt == '3' && *(fmt+1) == '2') {
        !           329:                                                        fmt += 2;
        !           330:                                                        modifier = LM_LONG;
        !           331:                                                } else {
        !           332: #ifdef _WIN64
        !           333:                                                        modifier = LM_LONG_LONG;
        !           334: #else
        !           335:                                                        modifier = LM_LONG;
        !           336: #endif
        !           337:                                                }
        !           338:                                        break;
        !           339:                                case 'l':
        !           340:                                        fmt++;
        !           341: #if SIZEOF_LONG_LONG
        !           342:                                        if (*fmt == 'l') {
        !           343:                                                fmt++;
        !           344:                                                modifier = LM_LONG_LONG;
        !           345:                                        } else
        !           346: #endif
        !           347:                                                modifier = LM_LONG;
        !           348:                                        break;
        !           349:                                case 'z':
        !           350:                                        fmt++;
        !           351:                                        modifier = LM_SIZE_T;
        !           352:                                        break;
        !           353:                                case 'j':
        !           354:                                        fmt++;
        !           355: #if SIZEOF_INTMAX_T
        !           356:                                        modifier = LM_INTMAX_T;
        !           357: #else
        !           358:                                        modifier = LM_SIZE_T;
        !           359: #endif
        !           360:                                        break;
        !           361:                                case 't':
        !           362:                                        fmt++;
        !           363: #if SIZEOF_PTRDIFF_T
        !           364:                                        modifier = LM_PTRDIFF_T;
        !           365: #else
        !           366:                                        modifier = LM_SIZE_T;
        !           367: #endif
        !           368:                                        break;
        !           369:                                case 'h':
        !           370:                                        fmt++;
        !           371:                                        if (*fmt == 'h') {
        !           372:                                                fmt++;
        !           373:                                        }
        !           374:                                        /* these are promoted to int, so no break */
        !           375:                                default:
        !           376:                                        modifier = LM_STD;
        !           377:                                        break;
        !           378:                        }
        !           379: 
        !           380:                        /*
        !           381:                         * Argument extraction and printing.
        !           382:                         * First we determine the argument type.
        !           383:                         * Then, we convert the argument to a string.
        !           384:                         * On exit from the switch, s points to the string that
        !           385:                         * must be printed, s_len has the length of the string
        !           386:                         * The precision requirements, if any, are reflected in s_len.
        !           387:                         *
        !           388:                         * NOTE: pad_char may be set to '0' because of the 0 flag.
        !           389:                         *   It is reset to ' ' by non-numeric formats
        !           390:                         */
        !           391:                        switch (*fmt) {
        !           392:                                case 'Z':
        !           393: #if SUHOSIN_PATCH
        !           394:                                        zend_suhosin_log(S_MISC, "'Z' specifier within format string");
        !           395:                                        goto skip_output;
        !           396: #else
        !           397:                                        zvp = (zval*) va_arg(ap, zval*);
        !           398:                                        zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
        !           399:                                        if (free_zcopy) {
        !           400:                                                zvp = &zcopy;
        !           401:                                        }
        !           402:                                        s_len = Z_STRLEN_P(zvp);
        !           403:                                        s = Z_STRVAL_P(zvp);
        !           404:                                        if (adjust_precision && precision < s_len) {
        !           405:                                                s_len = precision;
        !           406:                                        }
        !           407: #endif
        !           408:                                        break;
        !           409:                                case 'u':
        !           410:                                        switch(modifier) {
        !           411:                                                default:
        !           412:                                                        i_num = (wide_int) va_arg(ap, unsigned int);
        !           413:                                                        break;
        !           414:                                                case LM_LONG_DOUBLE:
        !           415:                                                        goto fmt_error;
        !           416:                                                case LM_LONG:
        !           417:                                                        i_num = (wide_int) va_arg(ap, unsigned long int);
        !           418:                                                        break;
        !           419:                                                case LM_SIZE_T:
        !           420:                                                        i_num = (wide_int) va_arg(ap, size_t);
        !           421:                                                        break;
        !           422: #if SIZEOF_LONG_LONG
        !           423:                                                case LM_LONG_LONG:
        !           424:                                                        i_num = (wide_int) va_arg(ap, u_wide_int);
        !           425:                                                        break;
        !           426: #endif
        !           427: #if SIZEOF_INTMAX_T
        !           428:                                                case LM_INTMAX_T:
        !           429:                                                        i_num = (wide_int) va_arg(ap, uintmax_t);
        !           430:                                                        break;
        !           431: #endif
        !           432: #if SIZEOF_PTRDIFF_T
        !           433:                                                case LM_PTRDIFF_T:
        !           434:                                                        i_num = (wide_int) va_arg(ap, ptrdiff_t);
        !           435:                                                        break;
        !           436: #endif
        !           437:                                        }
        !           438:                                        /*
        !           439:                                         * The rest also applies to other integer formats, so fall
        !           440:                                         * into that case.
        !           441:                                         */
        !           442:                                case 'd':
        !           443:                                case 'i':
        !           444:                                        /*
        !           445:                                         * Get the arg if we haven't already.
        !           446:                                         */
        !           447:                                        if ((*fmt) != 'u') {
        !           448:                                                switch(modifier) {
        !           449:                                                        default:
        !           450:                                                                i_num = (wide_int) va_arg(ap, int);
        !           451:                                                                break;
        !           452:                                                        case LM_LONG_DOUBLE:
        !           453:                                                                goto fmt_error;
        !           454:                                                        case LM_LONG:
        !           455:                                                                i_num = (wide_int) va_arg(ap, long int);
        !           456:                                                                break;
        !           457:                                                        case LM_SIZE_T:
        !           458: #if SIZEOF_SSIZE_T
        !           459:                                                                i_num = (wide_int) va_arg(ap, ssize_t);
        !           460: #else
        !           461:                                                                i_num = (wide_int) va_arg(ap, size_t);
        !           462: #endif
        !           463:                                                                break;
        !           464: #if SIZEOF_LONG_LONG
        !           465:                                                        case LM_LONG_LONG:
        !           466:                                                                i_num = (wide_int) va_arg(ap, wide_int);
        !           467:                                                                break;
        !           468: #endif
        !           469: #if SIZEOF_INTMAX_T
        !           470:                                                        case LM_INTMAX_T:
        !           471:                                                                i_num = (wide_int) va_arg(ap, intmax_t);
        !           472:                                                                break;
        !           473: #endif
        !           474: #if SIZEOF_PTRDIFF_T
        !           475:                                                        case LM_PTRDIFF_T:
        !           476:                                                                i_num = (wide_int) va_arg(ap, ptrdiff_t);
        !           477:                                                                break;
        !           478: #endif
        !           479:                                                }
        !           480:                                        }
        !           481:                                        s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
        !           482:                                                                &num_buf[NUM_BUF_SIZE], &s_len);
        !           483:                                        FIX_PRECISION(adjust_precision, precision, s, s_len);
        !           484: 
        !           485:                                        if (*fmt != 'u') {
        !           486:                                                if (is_negative)
        !           487:                                                        prefix_char = '-';
        !           488:                                                else if (print_sign)
        !           489:                                                        prefix_char = '+';
        !           490:                                                else if (print_blank)
        !           491:                                                        prefix_char = ' ';
        !           492:                                        }
        !           493:                                        break;
        !           494: 
        !           495: 
        !           496:                                case 'o':
        !           497:                                        switch(modifier) {
        !           498:                                                default:
        !           499:                                                        ui_num = (u_wide_int) va_arg(ap, unsigned int);
        !           500:                                                        break;
        !           501:                                                case LM_LONG_DOUBLE:
        !           502:                                                        goto fmt_error;
        !           503:                                                case LM_LONG:
        !           504:                                                        ui_num = (u_wide_int) va_arg(ap, unsigned long int);
        !           505:                                                        break;
        !           506:                                                case LM_SIZE_T:
        !           507:                                                        ui_num = (u_wide_int) va_arg(ap, size_t);
        !           508:                                                        break;
        !           509: #if SIZEOF_LONG_LONG
        !           510:                                                case LM_LONG_LONG:
        !           511:                                                        ui_num = (u_wide_int) va_arg(ap, u_wide_int);
        !           512:                                                        break;
        !           513: #endif
        !           514: #if SIZEOF_INTMAX_T
        !           515:                                                case LM_INTMAX_T:
        !           516:                                                        ui_num = (u_wide_int) va_arg(ap, uintmax_t);
        !           517:                                                        break;
        !           518: #endif
        !           519: #if SIZEOF_PTRDIFF_T
        !           520:                                                case LM_PTRDIFF_T:
        !           521:                                                        ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
        !           522:                                                        break;
        !           523: #endif
        !           524:                                        }
        !           525:                                        s = ap_php_conv_p2(ui_num, 3, *fmt,
        !           526:                                                                &num_buf[NUM_BUF_SIZE], &s_len);
        !           527:                                        FIX_PRECISION(adjust_precision, precision, s, s_len);
        !           528:                                        if (alternate_form && *s != '0') {
        !           529:                                                *--s = '0';
        !           530:                                                s_len++;
        !           531:                                        }
        !           532:                                        break;
        !           533: 
        !           534: 
        !           535:                                case 'x':
        !           536:                                case 'X':
        !           537:                                        switch(modifier) {
        !           538:                                                default:
        !           539:                                                        ui_num = (u_wide_int) va_arg(ap, unsigned int);
        !           540:                                                        break;
        !           541:                                                case LM_LONG_DOUBLE:
        !           542:                                                        goto fmt_error;
        !           543:                                                case LM_LONG:
        !           544:                                                        ui_num = (u_wide_int) va_arg(ap, unsigned long int);
        !           545:                                                        break;
        !           546:                                                case LM_SIZE_T:
        !           547:                                                        ui_num = (u_wide_int) va_arg(ap, size_t);
        !           548:                                                        break;
        !           549: #if SIZEOF_LONG_LONG
        !           550:                                                case LM_LONG_LONG:
        !           551:                                                        ui_num = (u_wide_int) va_arg(ap, u_wide_int);
        !           552:                                                        break;
        !           553: #endif
        !           554: #if SIZEOF_INTMAX_T
        !           555:                                                case LM_INTMAX_T:
        !           556:                                                        ui_num = (u_wide_int) va_arg(ap, uintmax_t);
        !           557:                                                        break;
        !           558: #endif
        !           559: #if SIZEOF_PTRDIFF_T
        !           560:                                                case LM_PTRDIFF_T:
        !           561:                                                        ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
        !           562:                                                        break;
        !           563: #endif
        !           564:                                        }
        !           565:                                        s = ap_php_conv_p2(ui_num, 4, *fmt,
        !           566:                                                                &num_buf[NUM_BUF_SIZE], &s_len);
        !           567:                                        FIX_PRECISION(adjust_precision, precision, s, s_len);
        !           568:                                        if (alternate_form && i_num != 0) {
        !           569:                                                *--s = *fmt;    /* 'x' or 'X' */
        !           570:                                                *--s = '0';
        !           571:                                                s_len += 2;
        !           572:                                        }
        !           573:                                        break;
        !           574: 
        !           575: 
        !           576:                                case 's':
        !           577:                                case 'v':
        !           578:                                        s = va_arg(ap, char *);
        !           579:                                        if (s != NULL) {
        !           580:                                                if (!adjust_precision) {
        !           581:                                                        s_len = strlen(s);
        !           582:                                                } else {
        !           583:                                                        s_len = strnlen(s, precision);
        !           584:                                                }
        !           585:                                        } else {
        !           586:                                                s = S_NULL;
        !           587:                                                s_len = S_NULL_LEN;
        !           588:                                        }
        !           589:                                        pad_char = ' ';
        !           590:                                        break;
        !           591: 
        !           592: 
        !           593:                                case 'f':
        !           594:                                case 'F':
        !           595:                                case 'e':
        !           596:                                case 'E':
        !           597:                                        switch(modifier) {
        !           598:                                                case LM_LONG_DOUBLE:
        !           599:                                                        fp_num = (double) va_arg(ap, long double);
        !           600:                                                        break;
        !           601:                                                case LM_STD:
        !           602:                                                        fp_num = va_arg(ap, double);
        !           603:                                                        break;
        !           604:                                                default:
        !           605:                                                        goto fmt_error;
        !           606:                                        }
        !           607: 
        !           608:                                        if (zend_isnan(fp_num)) {
        !           609:                                                s = "nan";
        !           610:                                                s_len = 3;
        !           611:                                        } else if (zend_isinf(fp_num)) {
        !           612:                                                s = "inf";
        !           613:                                                s_len = 3;
        !           614:                                        } else {
        !           615: #ifdef HAVE_LOCALE_H
        !           616:                                                if (!lconv) {
        !           617:                                                        lconv = localeconv();
        !           618:                                                }
        !           619: #endif
        !           620:                                                s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
        !           621:                                                 (adjust_precision == NO) ? FLOAT_DIGITS : precision,
        !           622:                                                 (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
        !           623:                                                                        &is_negative, &num_buf[1], &s_len);
        !           624:                                                if (is_negative)
        !           625:                                                        prefix_char = '-';
        !           626:                                                else if (print_sign)
        !           627:                                                        prefix_char = '+';
        !           628:                                                else if (print_blank)
        !           629:                                                        prefix_char = ' ';
        !           630:                                        }
        !           631:                                        break;
        !           632: 
        !           633: 
        !           634:                                case 'g':
        !           635:                                case 'k':
        !           636:                                case 'G':
        !           637:                                case 'H':
        !           638:                                        switch(modifier) {
        !           639:                                                case LM_LONG_DOUBLE:
        !           640:                                                        fp_num = (double) va_arg(ap, long double);
        !           641:                                                        break;
        !           642:                                                case LM_STD:
        !           643:                                                        fp_num = va_arg(ap, double);
        !           644:                                                        break;
        !           645:                                                default:
        !           646:                                                        goto fmt_error;
        !           647:                                        }
        !           648: 
        !           649:                                        if (zend_isnan(fp_num)) {
        !           650:                                                s = "NAN";
        !           651:                                                s_len = 3;
        !           652:                                                break;
        !           653:                                        } else if (zend_isinf(fp_num)) {
        !           654:                                                if (fp_num > 0) {
        !           655:                                                        s = "INF";
        !           656:                                                        s_len = 3;
        !           657:                                                } else {
        !           658:                                                        s = "-INF";
        !           659:                                                        s_len = 4;
        !           660:                                                }
        !           661:                                                break;
        !           662:                                        }
        !           663: 
        !           664:                                        if (adjust_precision == NO)
        !           665:                                                precision = FLOAT_DIGITS;
        !           666:                                        else if (precision == 0)
        !           667:                                                precision = 1;
        !           668:                                        /*
        !           669:                                         * * We use &num_buf[ 1 ], so that we have room for the sign
        !           670:                                         */
        !           671: #ifdef HAVE_LOCALE_H
        !           672:                                        if (!lconv) {
        !           673:                                                lconv = localeconv();
        !           674:                                        }
        !           675: #endif
        !           676:                                        s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
        !           677:                                        if (*s == '-')
        !           678:                                                prefix_char = *s++;
        !           679:                                        else if (print_sign)
        !           680:                                                prefix_char = '+';
        !           681:                                        else if (print_blank)
        !           682:                                                prefix_char = ' ';
        !           683: 
        !           684:                                        s_len = strlen(s);
        !           685: 
        !           686:                                        if (alternate_form && (strchr(s, '.')) == NULL)
        !           687:                                                s[s_len++] = '.';
        !           688:                                        break;
        !           689: 
        !           690: 
        !           691:                                case 'c':
        !           692:                                        char_buf[0] = (char) (va_arg(ap, int));
        !           693:                                        s = &char_buf[0];
        !           694:                                        s_len = 1;
        !           695:                                        pad_char = ' ';
        !           696:                                        break;
        !           697: 
        !           698: 
        !           699:                                case '%':
        !           700:                                        char_buf[0] = '%';
        !           701:                                        s = &char_buf[0];
        !           702:                                        s_len = 1;
        !           703:                                        pad_char = ' ';
        !           704:                                        break;
        !           705: 
        !           706: 
        !           707:                                case 'n':
        !           708: #if SUHOSIN_PATCH
        !           709:                                        zend_suhosin_log(S_MISC, "'n' specifier within format string");
        !           710: #else
        !           711:                                        *(va_arg(ap, int *)) = xbuf->len;
        !           712: #endif
        !           713:                                        goto skip_output;
        !           714: 
        !           715:                                        /*
        !           716:                                         * Always extract the argument as a "char *" pointer. We
        !           717:                                         * should be using "void *" but there are still machines
        !           718:                                         * that don't understand it.
        !           719:                                         * If the pointer size is equal to the size of an unsigned
        !           720:                                         * integer we convert the pointer to a hex number, otherwise
        !           721:                                         * we print "%p" to indicate that we don't handle "%p".
        !           722:                                         */
        !           723:                                case 'p':
        !           724:                                        if (sizeof(char *) <= sizeof(u_wide_int)) {
        !           725:                                                ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
        !           726:                                                s = ap_php_conv_p2(ui_num, 4, 'x',
        !           727:                                                                &num_buf[NUM_BUF_SIZE], &s_len);
        !           728:                                                if (ui_num != 0) {
        !           729:                                                        *--s = 'x';
        !           730:                                                        *--s = '0';
        !           731:                                                        s_len += 2;
        !           732:                                                }
        !           733:                                        } else {
        !           734:                                                s = "%p";
        !           735:                                                s_len = 2;
        !           736:                                        }
        !           737:                                        pad_char = ' ';
        !           738:                                        break;
        !           739: 
        !           740: 
        !           741:                                case NUL:
        !           742:                                        /*
        !           743:                                         * The last character of the format string was %.
        !           744:                                         * We ignore it.
        !           745:                                         */
        !           746:                                        continue;
        !           747: 
        !           748: 
        !           749: fmt_error:
        !           750:                                php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
        !           751:                                        /*
        !           752:                                         * The default case is for unrecognized %'s.
        !           753:                                         * We print %<char> to help the user identify what
        !           754:                                         * option is not understood.
        !           755:                                         * This is also useful in case the user wants to pass
        !           756:                                         * the output of format_converter to another function
        !           757:                                         * that understands some other %<char> (like syslog).
        !           758:                                         * Note that we can't point s inside fmt because the
        !           759:                                         * unknown <char> could be preceded by width etc.
        !           760:                                         */
        !           761:                                default:
        !           762:                                        char_buf[0] = '%';
        !           763:                                        char_buf[1] = *fmt;
        !           764:                                        s = char_buf;
        !           765:                                        s_len = 2;
        !           766:                                        pad_char = ' ';
        !           767:                                        break;
        !           768:                        }
        !           769: 
        !           770:                        if (prefix_char != NUL) {
        !           771:                                *--s = prefix_char;
        !           772:                                s_len++;
        !           773:                        }
        !           774:                        if (adjust_width && adjust == RIGHT && min_width > s_len) {
        !           775:                                if (pad_char == '0' && prefix_char != NUL) {
        !           776:                                        INS_CHAR(xbuf, *s);
        !           777:                                        s++;
        !           778:                                        s_len--;
        !           779:                                        min_width--;
        !           780:                                }
        !           781:                                PAD(xbuf, min_width - s_len, pad_char);
        !           782:                        }
        !           783:                        /*
        !           784:                         * Print the string s.
        !           785:                         */
        !           786:                        INS_STRING(xbuf, s, s_len);
        !           787: 
        !           788:                        if (adjust_width && adjust == LEFT && min_width > s_len)
        !           789:                                PAD(xbuf, min_width - s_len, pad_char);
        !           790:                        if (free_zcopy) {
        !           791:                                zval_dtor(&zcopy);
        !           792:                        }
        !           793:                }
        !           794: skip_output:
        !           795:                fmt++;
        !           796:        }
        !           797:        return;
        !           798: }
        !           799: /* }}} */
        !           800: 
        !           801: /*
        !           802:  * This is the general purpose conversion function.
        !           803:  */
        !           804: PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
        !           805: {
        !           806:        smart_str xbuf = {0};
        !           807: 
        !           808:        xbuf_format_converter(&xbuf, format, ap);
        !           809: 
        !           810:        if (max_len && xbuf.len > max_len) {
        !           811:                xbuf.len = max_len;
        !           812:        }
        !           813:        smart_str_0(&xbuf);
        !           814: 
        !           815:        *pbuf = xbuf.c;
        !           816: 
        !           817:        return xbuf.len;
        !           818: }
        !           819: /* }}} */
        !           820: 
        !           821: PHPAPI int spprintf(char **pbuf, size_t max_len, const char *format, ...) /* {{{ */
        !           822: {
        !           823:        int cc;
        !           824:        va_list ap;
        !           825: 
        !           826:        va_start(ap, format);
        !           827:        cc = vspprintf(pbuf, max_len, format, ap);
        !           828:        va_end(ap);
        !           829:        return (cc);
        !           830: }
        !           831: /* }}} */
        !           832: 
        !           833: /*
        !           834:  * Local variables:
        !           835:  * tab-width: 4
        !           836:  * c-basic-offset: 4
        !           837:  * End:
        !           838:  * vim600: sw=4 ts=4 fdm=marker
        !           839:  * vim<600: sw=4 ts=4
        !           840:  */

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