rfmtutil.c

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

C
993
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Run-time formatted I/O utility routines
*
****************************************************************************/


#include "ftnstd.h"
#include "rundat.h"
#include "errcod.h"
#include "fmtdef.h"
#include "intcnv.h"
#include "target.h"
#include "pgmacc.h"
#include "undefrtn.h"
#include "fltcnv.h"
#include "fmath.h"
#include "rmemmgr.h"

#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>

extern  void            SendEOR(void);
extern  void            SendStr(char PGM *,uint);
extern  void            SendChar(char,int);
extern  void            Drop(char);
extern  void            NextRec(void);
extern  void            IOErr(int,...);
extern  void            R_F2F(extended,char *,int,int,bool,int);
extern  void            R_F2E(extended,char *,int,int,bool,int,int,char);
extern  int             FmtS2I(char *,int,bool,intstar4 *,bool,int *);
extern  int             FmtS2F(char *,int,int,bool,int,int,extended *,bool,int *,bool);
extern  void            *RChkAlloc(uint);
extern  void            SetMaxPrec(int);
extern  void            BToHS(char *,int,char *);
extern  byte            Hex(byte);
extern  void            CheckCCtrl(void);
extern  void            R_FmtLog(uint);
extern  bool            __AllowCommaSep(void);

#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )

extern  const double __FAR      P1d100;
extern  const double __FAR      P1d_99;

typedef union bit_extended {
    char        pattern[16];
    extended    value;
} bit_extended;

typedef union bit_double {
    char        pattern[8];
    double      value;
} bit_double;

typedef union bit_float {
    char        pattern[4];
    float       value;
} bit_float;

static  const bit_extended __FAR XInfinity =
                            {   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                0xf0,0x7f,0x00,0x00,0x00,0x00,0x00,0x00 };
static  const bit_double __FAR  DInfinity =
                            { 0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x7f };
static  const bit_float __FAR   SInfinity = { 0x00,0x00,0x80,0x7f };

#endif

static  const byte __FAR        DataSize[] = {
            0,
            sizeof( logstar1 ),
            sizeof( logstar4 ),
            sizeof( intstar1 ),
            sizeof( intstar2 ),
            sizeof( intstar4 ),
            sizeof( single ),
            sizeof( double ),
            sizeof( extended ),
            sizeof( single ),
            sizeof( double ),
            sizeof( extended ) };


void    R_ChkType( PTYPE lower, PTYPE upper ) {
//===========================================

    if( ( IOCB->typ < lower ) || ( IOCB->typ > upper ) ) {
        IOErr( IO_FMT_MISMATCH );
    }
}


void    R_NewRec( void ) {
//==================

    if( IOCB->flags & IOF_OUTPT ) {
        IOCB->fileinfo->col = IOCB->fmtlen;
        CheckCCtrl();
        SendEOR();
        IOCB->fmtlen = IOCB->fileinfo->col;
    } else {
        NextRec();
    }
}


void    R_ChkIType( void ) {
//====================

// Check if type can be formatted using I format.

    if( ( IOCB->typ == PT_REAL_4 ) && ( IOCB->flags & IOF_EXTEND_FORMAT ) ) {
        // allow REAL variable containing integer data to be
        // formatted using I edit descriptor
        IOCB->typ = PT_INT_4;
    }
    R_ChkType( PT_INT_1, PT_INT_4 );
}


void    R_ChkFType( void ) {
//====================

// Check if type can be formatted using F, E, or D format.

    if( ( IOCB->typ == PT_INT_4 ) && ( IOCB->flags & IOF_EXTEND_FORMAT ) ) {
        // allow INTEGER variable containing floating-point data to be
        // formatted using F, E, or D edit descriptors
        IOCB->typ = PT_REAL_4;
    }
    R_ChkType( PT_REAL_4, PT_CPLX_32 );
}


void    R_ChkRecLen( void ) {
//=====================

    ftnfile     *fcb;

    fcb = IOCB->fileinfo;
    if( fcb->col > IOCB->fmtlen ) {
        IOCB->fmtlen = fcb->col;
    }
}


void    R_FOStr( void ) {
//=================

    FOString( IOCB->fmtptr->fmt4.fld1 );
}


uint    GetLen( void ) {
//================

    uint        len;

    if( IOCB->typ == PT_CHAR ) {
        len = IORslt.string.len;
    } else {
        len = DataSize[ IOCB->typ ];
    }
    return( len );
}


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

    ftnfile     *fcb;
    uint        length;

    fcb = IOCB->fileinfo;
    if( IOCB->typ != PT_CHAR ) {
        length = GetLen();
    } else {
        length = IORslt.string.len;
    }
    if( width == 0 ) {
        width = length;
    }
    if( fcb->col + width > fcb->bufflen ) {
        IOErr( IO_BUFF_LEN );
    }
    if( width > length ) {
        SendChar( ' ', width - length );
        width = length;
    }
    if( IOCB->typ == PT_CHAR ) {
        SendStrRtn( IORslt.string.strptr, width );
    } else {
        SendStrRtn( (char *)&IORslt, width );
    }
}


void    R_FIStr( void ) {
//=================

    uint        width;
    byte        blanks;
    uint        length;
    ftnfile     *fcb;
    char        *src;
    char        PGM *ptr;

    fcb   = IOCB->fileinfo;
    width = IOCB->fmtptr->fmt4.fld1;
    if( IOCB->typ != PT_CHAR ) {
        ptr = IORslt.pgm_ptr;
        length = GetLen();
    } else {
        ptr = IORslt.string.strptr;
        length = IORslt.string.len;
    }
    if( width == 0 ) {
        width = length;
    }
    if( width >= length ) {
        fcb->col += width - length;
        width = length;
    }
    ChkBuffLen( width );
    blanks = length - width;
    src = &fcb->buffer[ fcb->col ];
    pgm_memput( ptr, src, width );
    pgm_memset( ptr + width, ' ', blanks );
    fcb->col += width;
}


void    R_FOLog( void ) {
//=================

    if( UndefLogRtn() ) return;
    R_FmtLog( IOCB->fmtptr->fmt1.fld1 );
}


static  void    SetLogValue( logstar4 value ) {
//=============================================

    if( IOCB->typ == PT_LOG_1 ) {
        *(logstar1 PGM *)(IORslt.pgm_ptr) = value;
    } else {
        *(logstar4 PGM *)(IORslt.pgm_ptr) = value;
    }
}


void    R_FILog( void ) {
//=================

    ftnfile     *fcb;
    uint        width;
    char        ch;

    fcb = IOCB->fileinfo;
    width = IOCB->fmtptr->fmt1.fld1;
    ChkBuffLen( width );
    for(;;) {
        if( fcb->buffer[ fcb->col ] != ' ' ) break;
        fcb->col++;
        if( --width == 0 ) break;
    }
    if( fcb->buffer[ fcb->col ] == '.' ) {
         --width;
         fcb->col++;
    }
    if( width == 0 ) {
        IOErr( IO_BAD_CHAR );
    } else {
        ch = toupper( fcb->buffer[ fcb->col ] );
        if( ch == 'F' ) {
            SetLogValue( _LogValue( FALSE ) );
        } else if( ch == 'T' ) {
            SetLogValue( _LogValue( TRUE ) );
        }
    }
    if( __AllowCommaSep() ) { // don't flush but search for comma separator
        fcb->col++;
        width--;
        while( width > 0 ) {
            if( fcb->buffer[ fcb->col ] == ',' ) {
                fcb->col++;
                break;
            }
            fcb->col++;
            width--;
        }
    } else {
        fcb->col += width; // flush over other stuff
    }
}


void    R_FIFloat( void ) {
//===================

// Input an real or complex variable in D, E, F, G format.

    extended     value;
    fmt2 PGM    *fmtptr;
    ftnfile     *fcb;
    PTYPE       typ;
    int         prec;
    int         status;
    bool        comma;
    int         width;

    fcb = IOCB->fileinfo;
    fmtptr = &IOCB->fmtptr->fmt2;
    typ = IOCB->typ;
    ChkBuffLen( fmtptr->fld1 );
    switch( typ ) {
    case( PT_REAL_8 ):
    case( PT_CPLX_16 ):
        prec = PRECISION_DOUBLE;
        break;
    case( PT_REAL_16 ):
    case( PT_CPLX_32 ):
        prec = PRECISION_EXTENDED;
        break;
    default:
        prec = PRECISION_SINGLE;
    };
    comma = __AllowCommaSep();
    status = FmtS2F( &fcb->buffer[ fcb->col ], fmtptr->fld1,
                     fmtptr->fld2, ( fcb->blanks == BLANK_ZERO ),
                     IOCB->scale, prec, &value, comma, &width, FALSE );
    if( status == FLT_OK ) {
        if( comma && ( fmtptr->fld1 != width ) ) {
            fcb->col += width;
            if( fcb->buffer[ fcb->col ] == ',' ) {
                fcb->col++;
            } else {
                IOErr( IO_BAD_CHAR );
            }
        } else {
            fcb->col += fmtptr->fld1;
        }
        if( typ  == PT_REAL_4 ) {
            *(single PGM *)(IORslt.pgm_ptr) = value;
        } else if( typ  == PT_REAL_8 ) {
            *(double PGM *)(IORslt.pgm_ptr) = value;
        } else if( typ  == PT_REAL_16 ) {
            *(extended PGM *)(IORslt.pgm_ptr) = value;
        } else if( typ  == PT_CPLX_8 ) {
            if( IOCB->flags & IOF_FMTREALPART ) {
                ((complex PGM *)(IORslt.pgm_ptr))->realpart = value;
            } else {
                ((complex PGM *)(IORslt.pgm_ptr))->imagpart = value;
            }
        } else if( typ  == PT_CPLX_16 ) {
            if( IOCB->flags & IOF_FMTREALPART ) {
                ((dcomplex PGM *)(IORslt.pgm_ptr))->realpart = value;
            } else {
                ((dcomplex PGM *)(IORslt.pgm_ptr))->imagpart = value;
            }
        } else {
            if( IOCB->flags & IOF_FMTREALPART ) {
                ((xcomplex PGM *)(IORslt.pgm_ptr))->realpart = value;
            } else {
                ((xcomplex PGM *)(IORslt.pgm_ptr))->imagpart = value;
            }
        }
    } else {
        if( status == FLT_INVALID ) {
            IOErr( IO_BAD_CHAR );
        } else { // FLT_RANGE_EXCEEDED
            IOErr( IO_FRANGE_EXCEEDED );
        }
    }
}


bool    GetReal( extended *value ) {
//================================

    PTYPE       typ;
    single      *short_flt;
    bool        defined;

    typ = IOCB->typ;
    if( ( typ == PT_REAL_4  ) || ( typ == PT_CPLX_8 ) ) {
        SetMaxPrec( MAX_SP );
        if( typ  == PT_REAL_4 ) {
            short_flt = &IORslt.single;
        } else if( IOCB->flags & IOF_FMTREALPART ) {     // PT_CPLX_8
            short_flt = &IORslt.complex.realpart;
        } else {
            short_flt = &IORslt.complex.imagpart;
        }
        *value = *short_flt;
        defined = !UndefRealRtn( short_flt );
    } else if( ( typ == PT_REAL_8 ) || ( typ == PT_CPLX_16 ) ) {
        SetMaxPrec( MAX_DP );
        if( typ == PT_REAL_8 ) {
            *value = IORslt.dble;
        } else if( IOCB->flags & IOF_FMTREALPART ) {    // PT_CPLX_16
            *value = IORslt.dcomplex.realpart;
        } else {
            *value = IORslt.dcomplex.imagpart;
        }
        defined = !UndefDoubleRtn( value );
    } else {
        SetMaxPrec( MAX_XP );
        if( typ == PT_REAL_16 ) {
            *value = IORslt.extended;
        } else if( IOCB->flags & IOF_FMTREALPART ) {    // PT_CPLX_32
            *value = IORslt.xcomplex.realpart;
        } else {
            *value = IORslt.xcomplex.imagpart;
        }
        defined = !UndefExtendedRtn( value );
    }
    return( defined );
}


void    R_FOF( void ) {
//===============

    ftnfile     *fcb;
    fmt2 PGM    *fmt;
    char        *buf;
    uint        wid;
    extended    val;

    fcb = IOCB->fileinfo;
    buf = &fcb->buffer[ fcb->col ];
    fmt = &IOCB->fmtptr->fmt2;
    wid = fmt->fld1;
    if( GetRealRtn( &val, wid ) ) {
        R_F2F( val, buf, wid, fmt->fld2, (IOCB->flags & IOF_PLUS) != 0,
               IOCB->scale );
    }
    fcb->col += wid;
}


void    R_FOE( int exp, char ch ) {
//=================================

    ftnfile     *fcb;
    fmt3 PGM    *fmt;
    char        *buf;
    uint        wid;
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
    extended      absvalue;
#endif
    extended      value;
    extended      bot;
    extended      top;

    fcb = IOCB->fileinfo;
    buf = &fcb->buffer[ fcb->col ];
    fmt = &IOCB->fmtptr->fmt3;
    wid = fmt->fld1;
    if( GetRealRtn( &value, wid ) ) {
        // if Ew.d or Dw.d format, exp == 0
        // (i.e. exponent width not specified)
        if( exp == 0 ) {
#if defined( _M_IX86 ) || defined( __AXP__ ) || defined( __PPC__ )
            absvalue = value;
            if( value < 0.0 ) {
                absvalue = -value;
            }

⌨️ 快捷键说明

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