prtf.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,101 行 · 第 1/3 页

C
1,101
字号
        ctl++;
        break;
    case 'h':
        if( ctl[1] == 'h' ) {
            specs->_flags |= SPF_CHAR;
            ctl += 2;
            break;
        }
        specs->_flags |= SPF_SHORT;
        ctl++;
        break;
#if defined( __LONG_LONG_SUPPORT__ )
    case 'I':
        if(( ctl[1] == '6' ) && ( ctl[2] == '4' )) {
            specs->_flags |= SPF_LONG_LONG;
            ctl += 3;
        }
        break;
    JSPEC_CASE_LLONG
        /* fall through */
#endif
    case 'L':
        specs->_flags |= SPF_LONG_DOUBLE | SPF_LONG_LONG;
        ctl++;
        break;
#if defined( __FAR_SUPPORT__ )
    case 'F':                   /* conflicts with ISO-defined 'F' conversion */
        /* fall through */
#endif
    case 'W':                   /* 8086 specific flag for FAR pointer */
        specs->_flags |= SPF_FAR;
        ctl++;
        break;
    case 'N':                   /* 8086 specific flag for NEAR pointer */
        specs->_flags |= SPF_NEAR;
        ctl++;
        break;
#if defined( TSPEC_IS_INT ) || defined( ZSPEC_IS_INT )
    TSPEC_CASE_INT      /* If either 't' or 'z' spec corresponds to 'int',  */
    ZSPEC_CASE_INT      /* we need to parse and ignore the spec.            */
        ctl++;
        break;
#endif
    }
    return( ctl );
}


static const CHAR_TYPE *evalflags( const CHAR_TYPE *ctl, SPECS __SLIB *specs )
{
    specs->_flags = 0;
    for( ; ; ctl++ ) {
        if( *ctl == '-' ) {
            specs->_flags |= SPF_LEFT_ADJUST;
        } else if( *ctl == '#' ) {
            specs->_flags |= SPF_ALT;
        } else if( *ctl == '+' ) {
            specs->_flags |= SPF_FORCE_SIGN;
            specs->_flags &= ~SPF_BLANK;
        } else if( *ctl == ' ' ) {
            if( ( specs->_flags & SPF_FORCE_SIGN ) == 0 ) {
                specs->_flags |= SPF_BLANK;
            }
        } else if( *ctl == '0' ) {
            specs->_pad_char = '0';
#ifdef __QNX__
            specs->_flags |= SPF_ZERO_PAD;
#endif
        } else {
            break;
        }
    }
    return( ctl );
}


static int far_strlen( FAR_STRING s, int precision )
{
    int     len;

    len = 0;
    while(( len != precision ) && ( *s++ != NULLCHAR ))
        ++len;

    return( len );
}

/*
 * far_other_strlen - calculates the length of an ascii string
 *                    for the unicode version
 *                  - calculates the length of a unicode string for
 *                    the standard version
 */

static int far_other_strlen( FAR_STRING s, int precision )
{
    int                 len = 0;
    _FAR_OTHER_STRING   ptr = (_FAR_OTHER_STRING)s;

#if !defined( __WIDECHAR__ ) && defined( USE_MBCS_TRANSLATION )
    char                mbBuf[MB_CUR_MAX];
    int                 chBytes;

    if( precision == -1 ) {
        while( *ptr ) {
            chBytes = wctomb( mbBuf, *ptr++ );
            if( chBytes != -1 ) {
                len += chBytes;
            }
        }
        return( len );
    }
    while( *ptr && ( len <= precision )) {
        chBytes = wctomb( mbBuf, *ptr++ );
        if( chBytes != -1 ) {
            len += chBytes;
        }
    }
    return(( len <= precision ) ? len : precision );

#else

    while( *ptr++ && ( len != precision ))
        ++len;

    return( len );
#endif
}

static void fmt4hex( unsigned value, CHAR_TYPE *buf, int maxlen )
{
    int     i, len;

    __F_NAME(itoa,_itow)( value, buf, 16 );
    len = __F_NAME(strlen,wcslen)( buf );
    for( i = maxlen - 1; len; --i ) {
        --len;
        buf[i] = buf[len];
    }
    while( i >= 0 ) {
        buf[i] = '0';
        --i;
    }
    buf[maxlen] = NULLCHAR;
}


static void FixedPoint_Format( CHAR_TYPE *buf, long value, SPECS __SLIB *specs )
{
    T32         at;
    int         i;
    CHAR_TYPE   *bufp;

    at.sWhole = value;
    if( at.sWhole < 0 ) {
        at.sWhole = - at.sWhole;
        *buf++ = '-';
    }
    if( specs->_prec == -1 )
        specs->_prec = 4;

    __F_NAME(itoa,_itow)( at.wd.hi, buf, 10 );
    bufp = buf;         /* remember start address of buffer */
    while( *buf )
        ++buf;

    if( specs->_prec != 0 ) {
        *buf++ = '.';
        for( i = 0; i < specs->_prec; i++ ) {
            at.wd.hi = 0;
            at.uWhole *= 10;
            *buf++ = at.bite.b3 + '0';
        }
        *buf = NULLCHAR;
    }
    if( at.wd.lo & 0x8000 ) {   /* fraction >= .5, need to round */
        for(;;) {                               /* 22-dec-91 */
            if( buf == bufp ) {
                *buf++ = '1';
                while( *buf == '0' )
                    ++buf;

                if( *buf == '.' ) {
                    *buf++ = '0';
                    *buf++ = '.';
                    while( *buf == '0' ) {
                        ++buf;
                    }
                }
                *buf++ = '0';
                *buf = NULLCHAR;
                break;
            }
            --buf;
            if( *buf == '.' )
                --buf;

            if( *buf != '9' ) {
                ++ *buf;
                break;
            }
            *buf = '0';
        }
    }
}

static void float_format( CHAR_TYPE *buffer, my_va_list *pargs, SPECS __SLIB *specs )
{
#ifdef __WIDECHAR__
    char                mbBuffer[BUF_SIZE*MB_CUR_MAX];
    _mbcs_SPECS         mbSpecs;
    int                 count;
    size_t              rc;
    char                *p;
#endif // __WIDECHAR__

#ifdef __WIDECHAR__
    /*
     * EFG_PRINTF can only handle MBCS buffers and the MBCS version of the
     * SPECS structure.  So, make a _mbcs_SPECS structure equivalent to the
     * _wide_SPECS one, and use that instead.  Note that we can't use
     * memcpy() because some field sizes are different.
     */
    mbSpecs._dest = NULL;               /* this field isn't actually used */
    mbSpecs._flags = specs->_flags;
    mbSpecs._version = specs->_version;
    mbSpecs._fld_width = specs->_fld_width;
    mbSpecs._prec = specs->_prec;
    mbSpecs._output_count = specs->_output_count;
    mbSpecs._n0 = specs->_n0;
    mbSpecs._nz0 = specs->_nz0;
    mbSpecs._n1 = specs->_n1;
    mbSpecs._nz1 = specs->_nz1;
    mbSpecs._n2 = specs->_n2;
    mbSpecs._nz2 = specs->_nz2;
    mbSpecs._character = (char)specs->_character;
    mbSpecs._pad_char = (char)specs->_pad_char;
#endif

#ifdef __WIDECHAR__
    EFG_PRINTF( mbBuffer, pargs, &mbSpecs );
#else
    EFG_PRINTF( buffer, pargs, specs );
#endif

#ifdef __WIDECHAR__
    /*
     * Now convert the returned information back into our _wide_SPECS
     * structure.  We can't just use mbstowcs because it's an array of
     * characters, not a string.
     */
    p = mbBuffer;
    for( count = 0; count < BUF_SIZE; count++ ) {
        rc = mbtowc( &(buffer[count]), p, MB_CUR_MAX );
        if( rc == -1 ) {
            buffer[count] = L'?';
        }
        p = _mbsinc( p );
    }
    specs->_flags = mbSpecs._flags;
    specs->_version = mbSpecs._version;
    specs->_fld_width = mbSpecs._fld_width;
    specs->_prec = mbSpecs._prec;
    specs->_output_count = mbSpecs._output_count;
    specs->_n0 = mbSpecs._n0;
    specs->_nz0 = mbSpecs._nz0;
    specs->_n1 = mbSpecs._n1;
    specs->_nz1 = mbSpecs._nz1;
    specs->_n2 = mbSpecs._n2;
    specs->_nz2 = mbSpecs._nz2;
    specs->_character = (wchar_t) mbSpecs._character;
    specs->_pad_char = (wchar_t) mbSpecs._pad_char;
#endif
}

static void SetZeroPad( SPECS __SLIB *specs )
{
    int         n;

    if( !(specs->_flags & SPF_LEFT_ADJUST) ) {
        if( specs->_pad_char == '0' ) {
            n = specs->_fld_width - specs->_n0 - specs->_nz0 -
                    specs->_n1 - specs->_nz1 - specs->_n2 - specs->_nz2;
            if( n > 0 ) {
                specs->_nz0 += n;
            }
        }
    }
}


#if !defined( __WIDECHAR__ ) && defined( USE_MBCS_TRANSLATION )
static void write_wide_string( FAR_UNI_STRING str, SPECS *specs,
                               slib_callback_t *out_putc )
{
    int     bytes;
    char    mbBuf[MB_CUR_MAX];
    char    *mbBufPtr;

    while( specs->_n1 > 0 ) {
        bytes = wctomb( mbBuf, *str++ );
        if( bytes != -1 ) {
            if( bytes <= specs->_n1 ) {
                mbBufPtr = mbBuf;
                while( bytes-- ) {
                    (out_putc)( specs, *mbBufPtr++ );
                    --specs->_n1;
                }
            } else {
                specs->_n1 = 0;
            }
        }
    }
}
#endif


#if defined( __WIDECHAR__ ) && defined( USE_MBCS_TRANSLATION )
static void write_skinny_string( FAR_ASCII_STRING str, SPECS *specs,
                                 slib_callback_t *out_putc )
{
    int                 bytes;
    wchar_t             wc;
    FAR_ASCII_STRING    mbPtr = str;
    char                mbBuf[MB_CUR_MAX];

    while( specs->_n1 > 0 ) {
        mbBuf[0] = *mbPtr++;
        if( _ismbblead( mbBuf[0] ) )
            mbBuf[1] = *mbPtr++;

        bytes = mbtowc( &wc, mbBuf, MB_CUR_MAX );
        if( bytes <= specs->_n1 ) {
            if( bytes != -1 ) {
                (out_putc)( specs, wc );
                specs->_n1 -= bytes;
            }
        } else {
            specs->_n1 = 0;
        }
    }
}
#endif


static FAR_STRING formstring( CHAR_TYPE *buffer, my_va_list *pargs,
                              SPECS __SLIB *specs, CHAR_TYPE *null_string )
{
    FAR_STRING              arg;
    int                     length;
    int                     radix;
#if defined( __LONG_LONG_SUPPORT__ )
    unsigned long long      long_long_value;
#endif
    unsigned long           long_value;
    unsigned int            int_value;
#if defined( __FAR_SUPPORT__ )
    unsigned int            seg_value;
#endif
#if !defined( __WIDECHAR__ ) && defined( USE_MBCS_TRANSLATION )
    int                     bytes;
#endif

    arg = buffer;

    specs->_n0 = specs->_nz0 =
    specs->_n1 = specs->_nz1 =

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?