rfmtutil.c

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

C
993
字号
            top = P1d100;
            if( IOCB->scale != 0 ) { // we must shift the range of our check;
                bot = pow( 10, IOCB->scale );
                top *= bot;
                bot *= P1d_99;
            } else {
                bot = P1d_99;
            }

            if( ( ( absvalue <= bot ) || ( absvalue >= top ) ) &&
                ( absvalue != 0.0 ) ) {
                ch = NULLCHAR;   // no exponent letter
                exp = 3;
            } else {
#endif
                exp = 2;
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
            }
#endif
        }
        R_F2E( value, buf, wid, fmt->fld2, (IOCB->flags & IOF_PLUS) != 0,
               IOCB->scale, exp, ch );
    }
    fcb->col += wid;
}


bool    FmtH2B( char *src, uint width, char PGM *dst, int len, PTYPE typ ) {
//==========================================================================

    char        ch1;
    byte        ch2;
    bool        valid;
    char        *stop;

#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
#else
    typ = typ;
#endif
    pgm_memset( dst, 0, len );
    if( width >= 2 * len ) {
        len *= 2;
        src += width - len;
    } else {
        len = width;
    }
    stop = src + len;
    ch1 = '0';
    if( ( len & 1 ) == 0 ) {
        ch1 = *src;
        src++;
    }
    ch2 = *src;
    src++;
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
    if( typ != PT_CHAR ) {
        ++len;
        len &= ~1;
        len /= 2;
        dst += len - 1;
    }
#endif
    for(;;) {
        valid = FALSE;
        if( !isxdigit( ch1 ) ) {
            if( ch1 != ' ' ) break;
            ch1 = '0';
        }
        if( !isxdigit( ch2 ) ) {
            if( ch2 != ' ' ) break;
            ch2 = '0';
        }
        valid = TRUE;
        *dst = ( Hex( ch1 ) << 4 ) + Hex( ch2 );
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
        if( typ == PT_CHAR ) {
            ++dst;
        } else {
            --dst;
        }
#else
        dst++;
#endif
        if( src == stop ) break;
        ch1 = *src;
        src++;
        ch2 = *src;
        src++;
    }
    return( valid );
}


void    R_FIHex( void ) {
//=================

    uint        width;
    int         len;
    ftnfile     *fcb;
    PTYPE       typ;
    void        PGM *ptr;

    fcb = IOCB->fileinfo;
    width = IOCB->fmtptr->fmt1.fld1;
    len =  GetLen();
    typ = IOCB->typ;
    ChkBuffLen( width );
    if( typ == PT_CHAR ) {
        ptr = IORslt.string.strptr;
    } else {
        ptr = IORslt.pgm_ptr;
        if( typ == PT_CPLX_8 ) {
            if( IOCB->flags & IOF_FMTREALPART ) {
                ptr = &((complex *)ptr)->realpart;
            } else {
                ptr = &((complex *)ptr)->imagpart;
            }
        } else if( typ == PT_CPLX_16 ) {
            if( IOCB->flags & IOF_FMTREALPART ) {
                ptr = &((dcomplex *)ptr)->imagpart;
            } else {
                ptr = &((dcomplex *)ptr)->imagpart;
            }
        }
    }
    if( !FmtH2B( &fcb->buffer[ fcb->col ], width, ptr, len, typ ) ) {
        IOErr( IO_BAD_CHAR );
    }
    fcb->col += width;
}


void    R_FOHex( void ) {
//=================

    FOHex( IOCB->fmtptr->fmt1.fld1 );
}


void    FOHex( uint width ) {
//===========================

    uint        len;
    int         trunc;
    ftnfile     *fcb;
    PTYPE       typ;
    char        *buff;

    fcb = IOCB->fileinfo;
    typ = IOCB->typ;
    len = GetLen();
    trunc = 0;

//  Use this method when real and imaginary parts are formatted using
//  one edit descriptor:
/*
    if( ( IOCB->typ == PT_CPLX_8 ) || ( IOCB->typ == PT_CPLX_16 ) ) {
        len *= 2;
        IOCB->flags &= ~IOF_FMTREALPART;  // we'll print both parts at once
    }
*/
//  Use this method when real and imaginary parts each require an
//  edit descriptor:

    if( IOCB->typ == PT_CPLX_8 ) {
        if( !(IOCB->flags & IOF_FMTREALPART) ) {
            IORslt.complex.realpart = IORslt.complex.imagpart;
        }
    } else if( IOCB->typ == PT_CPLX_16 ) {
        if( !(IOCB->flags & IOF_FMTREALPART) ) {
            IORslt.dcomplex.realpart = IORslt.dcomplex.imagpart;
        }
    } else if( IOCB->typ == PT_CPLX_32 ) {
        if( !(IOCB->flags & IOF_FMTREALPART) ) {
            IORslt.xcomplex.realpart = IORslt.xcomplex.imagpart;
        }
    }
    if( width == 0 ) {
        width = 2*len;
    }

    trunc = ( len * 2 ) - width;
    if( trunc < 0 ) {
        SendChar( ' ', -trunc );
    }
    if( trunc <= 0 ) {
        trunc = 0;
    }

    if( typ != PT_CHAR ) {
        len *= 2;
        HexFlip( (char *)&IORslt, len );
        BToHS( (char *)&IORslt , len, IOCB->buffer );
        strupr( IOCB->buffer );
        SendStr( IOCB->buffer + trunc, len - trunc );
    } else {
        buff = IOCB->buffer;
        len *= 2;
        if( len > IO_FIELD_BUFF ) {
            buff = RChkAlloc( len + 1 );
        }
        pgm_BToHS( IORslt.string.strptr, len, buff );
        strupr( buff );
        SendStr( buff + trunc, len - trunc );
        if( len > IO_FIELD_BUFF ) {
            RMemFree( buff );
        }
    }
}


static  void    HexFlip( char *src, int len ) {
//=============================================

// Convert number to hex string.

    char        *ptr;
    char        *last;
    int         num_len;
    char        tmp;

    ptr = src;
    num_len = len / 2;
    last = src + num_len - 1;
    while( num_len > 0 ) {
        tmp = *ptr;
        *ptr = *last;
        *last = tmp;
        ptr++;
        last--;
        num_len -= 2;
    }
}


void    R_FIInt( void ) {
//=================

    intstar4    value;
    uint        width;
    int         new_width;
    int         status;
    ftnfile     *fcb;
    bool        comma;

    fcb = IOCB->fileinfo;
    width = IOCB->fmtptr->fmt2.fld1;
    ChkBuffLen( width );
    comma = __AllowCommaSep();
    status = FmtS2I( &fcb->buffer[ fcb->col ], width,
                     ( fcb->blanks == BLANK_ZERO ), &value, comma, &new_width );
    if( status == INT_INVALID ) {
        IOErr( IO_BAD_CHAR );
    } else if( status == INT_OVERFLOW ) {
        IOErr( IO_IOVERFLOW );
    } else {
        if( comma && ( width != new_width ) ) { // use comma as field separator
            fcb->col += new_width;
            if( fcb->buffer[ fcb->col ] == ',' ) {
                fcb->col++;
            } else {
                IOErr( IO_BAD_CHAR );
            }
        } else {
            fcb->col += width;
        }
        if( IOCB->typ == PT_INT_1 ) {
            *(intstar1 PGM *)(IORslt.pgm_ptr) = value;
        } else if( IOCB->typ == PT_INT_2 ) {
            *(intstar2 PGM *)(IORslt.pgm_ptr) = value;
        } else {
            *(intstar4 PGM *)(IORslt.pgm_ptr) = value;
        }
    }
}


void    R_FOInt( void ) {
//=================

    OutInt( IOCB->fmtptr->fmt2.fld1, IOCB->fmtptr->fmt2.fld2 );
}


static  void    OutInt( uint width, uint min ) {
//==============================================

    char        *number;
    uint        length;
    uint        space;
    bool        minus;
    intstar4    iorslt;

    if( UndefIntRtn( width ) ) return;
    iorslt = IORslt.intstar4;
    if( ( iorslt == 0 ) && ( min == 0 ) ) {
        SendChar( ' ', width );
    } else {
        minus = ( iorslt < 0 );
        number = IOCB->buffer;
        if( minus ) {
            number++; // skip the minus sign
        }
        ltoa( iorslt, IOCB->buffer, 10 );
        length = strlen( number );
        if( length > min ) {
            min = length;
        }
        if( min <= width ) {
            space = width - min;
            if( minus || ( IOCB->flags & IOF_PLUS ) ) {
                if( space != 0 ) {
                    SendChar( ' ', space - 1 );
                    if( minus ) {
                        Drop( '-' );
                    } else {
                        Drop( '+' );
                    }
                    SendChar( '0', min - length );
                    SendStr( number, length );
                } else {
                    SendChar( '*', width );
                }
            } else {
                SendChar( ' ', space );
                SendChar( '0', min - length );
                SendStr( number, length );
            }
        } else {
            SendChar( '*', width );
        }
    }
}


static  int     Div10S( real val ) {
//==================================

    int         retn;

    if( val < SInfinity.value ) {
        retn = -1;
        while( val >= 1 ) {
          retn++;
          val /= 10;
        }
        return( retn );
    } else {
        return( INT_MAX );
    }
}


    //  this function is called to determine if a number printed in G
    //  format is printed with the E format or the F format

static  int     Div10L( double val ) {
//====================================

    int         retn;

    unsigned short int * ui = (unsigned short int *) & val;
    if ( (ui [3] & 0x7FF0) == 0x7FF0 ) {    /* NaN or Inf */
        return( INT_MAX );
    }

    if ( val < DInfinity.value ) {
        retn = -1;
        while( val >= 1 ) {
          retn++;
              //   check for runaway due to a NaN
          // if ( retn == 1000 )
             // return ( INT_MAX );
          val /= 10;
        }
        return( retn );
    } else {
        return( INT_MAX );
    }
}


static  int     Div10X( extended val ) {
//======================================

    int         retn;

    if( val < XInfinity.value ) {
        retn = -1;
        while( val >= 1 ) {
          retn++;
          val /= 10;
        }
        return( retn );
    } else {
        return( INT_MAX );
    }
}


void    R_FOG( void ) {
//===============

    int         width;
    int         dec;
    int         exp;
    int         logval;
    char        *buf;
    ftnfile     *fcb;
    char        ch;
    extended    value;
    extended    absvalue;

    width = IOCB->fmtptr->fmt3.fld1;
    dec = IOCB->fmtptr->fmt3.fld2;
    exp = IOCB->fmtptr->fmt3.fld3;
    fcb = IOCB->fileinfo;
    buf = &fcb->buffer[ fcb->col ];
    if( IOCB->typ <= PT_LOG_4 ) {
        R_FOLog();
    } else if( IOCB->typ <= PT_INT_4 ) {
        OutInt( width, 1 );
    } else {
        if( GetRealRtn( &value, width ) ) {
            absvalue = value;
            if( value < 0.0 ) {
                absvalue = -value;
            }
            /* round to "dec" digits */
            absvalue = absvalue + .5 * pow( 10, -dec );
            if( ( IOCB->typ == PT_REAL_4 ) || ( IOCB->typ == PT_CPLX_8 ) ) {
                logval = Div10S( absvalue );
            } else if((IOCB->typ == PT_REAL_8) || (IOCB->typ == PT_CPLX_16)) {
                logval = Div10L( absvalue );
            } else {
                logval = Div10X( absvalue );
            }
            if( ( absvalue < 0.1 ) || ( logval >= dec ) ) {
                ch = 'E';
                if( exp == 0 ) { // if Gw.d
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
                    if( ( ( absvalue <= P1d_99 ) || ( absvalue >= P1d100 ) ) &&
                        ( absvalue != 0.0 ) ) {
                        ch = NULLCHAR;   // no exponent letter
                        exp = 3;
                    } else {
#endif
                        exp = 2;
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
                    }
#endif
                }
                R_F2E( value, buf, width, dec, (IOCB->flags & IOF_PLUS) != 0,
                       IOCB->scale, exp, ch );
                fcb->col += width;
            } else {
                if( exp == 0 ) { // if Gw.d
                    exp = 4;
                } else {
                    exp += 2;
                }
                width -= exp;
                if( width > 0 ) {
                    dec -= ( logval + 1 );
                    if( ( dec <= width ) && ( dec >= 0 ) ) {
                        R_F2F( value, buf, width, dec,
                               ( IOCB->flags & IOF_PLUS ) != 0, 0 );
                        fcb->col += width;
                        if( *buf == '*' ) {
                            // fill remaining field
                            SendChar( '*', exp );
                        } else {
                            SendChar( ' ', exp );
                        }
                    } else {
                        SendChar( '*', width + exp );
                    }
                } else {
                    SendChar( '*', width + exp );
                }
            }
        } else { // undefined chars will be filled in for value
            fcb->col += width;
        }
    }
}


void    ChkBuffLen( uint width ) {
//================================

    if( IOCB->fileinfo->col + width > IOCB->fileinfo->len ) {
        IOErr( IO_BUFF_LEN );
    }
}

⌨️ 快捷键说明

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