cfconv.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 590 行 · 第 1/2 页
C
590 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include <stddef.h>
#include "watcom.h"
#include "cfloat.h"
#include "machine.h"
#include "i64.h"
#define NULLCHAR '\0'
extern unsigned_32 U32ModDiv(unsigned_32*,unsigned_32);
#define _IsDigit( ch ) ( ch >= '0' && ch <= '9' )
extern signed_64 CFGetDec64( char *bstart ) {
/**************************************************/
signed_64 number;
signed_64 ten;
signed_64 temp;
I32ToI64( 0, &number );
I32ToI64( 10, &ten );
while( _IsDigit( *bstart ) ) {
U64Mul( &number, &ten, &number );
I32ToI64( *bstart++ - '0', &temp );
U64Add( &number, &temp, &number );
}
return( number );
}
extern signed_32 CFGetDec32( char *bstart ) {
/**************************************************/
signed_32 number;
number = 0;
while( _IsDigit( *bstart ) ) {
number = number * 10 + *bstart++ - '0';
}
return( number );
}
static signed_16 CFGetDec16( char *bstart ) {
/**************************************************/
signed_16 number;
number = 0;
while( _IsDigit( *bstart ) ) {
number = number * 10 + *bstart++ - '0';
}
return( number );
}
extern char *CFCnvFS( cfloat *f, char *buffer, int maxlen ) {
/***************************************************************/
int len;
len = f->len - 1;
if( len + 5 + I16DIGITS > maxlen ) {
len = maxlen - 5 - I16DIGITS;
}
if( f->sign == -1 ) {
*buffer++ = '-';
}
*buffer++ = f->mant[0];
*buffer++ = '.'; /* don't forget decimal point!*/
memcpy( buffer, &f->mant[1], len ); /* copy mantissa*/
buffer += len;
*buffer++ = 'E';
len = f->exp - 1;
if( len < 0 ) {
*buffer++ = '-';
len = -len;
}
buffer[ 2 ] = len % 10 + '0';
len /= 10;
buffer[ 1 ] = len % 10 + '0';
len /= 10;
buffer[ 0 ] = len + '0';
buffer[ 3 ] = NULLCHAR;
buffer += 3;
return( buffer );
}
static void DoConvert( cfloat *number, char *bstart ) {
/*****************************************************************/
int len;
char *fptr;
int sgn;
int expon;
for(;;) {
if( *bstart != ' ' ) break;
bstart++;
}
sgn = 1;
if( *bstart == '-' ) {
sgn = -1;
bstart++;
} else if( *bstart == '+' ) {
bstart++;
}
expon = 0;
len = 0;
fptr = number->mant;
if( _IsDigit( *bstart ) ) {
for(;;) { /* scan before decimal point*/
*fptr++ = *bstart++;
len++;
expon++;
if( !_IsDigit( *bstart ) ) break;
}
if( *bstart == '.' ) {
bstart++;
for(;;) { /* scan after decimal point*/
if( !_IsDigit( *bstart ) ) break;
*fptr++ = *bstart++;
len++;
}
}
} else {
if( *bstart != '.' ) return;
++bstart;
if( !_IsDigit( *bstart ) ) return;
for(;;) { /* scan after decimal point*/
*fptr++ = *bstart++;
len++;
if( !_IsDigit( *bstart ) ) break;
}
}
if( *bstart == 'E' || *bstart == 'e' ) {
if( *++bstart == '-' ) {
expon -= CFGetDec16( ++bstart );
} else {
if( *bstart == '+' ) {
bstart++;
}
expon += CFGetDec16( bstart );
}
}
number->sign = sgn;
number->len = len; /* fill in length*/
number->exp = expon;
CFClean( number );
}
extern cfloat *CFCnvSF( char *bstart, char *bend ) {
/****************************************************/
/* Syntax accepted by this converter:*/
/**/
/* { at least 0 blanks } < - | + >*/
/* { at least 1 digit } < . { at least 0 digits } >*/
/* or . { at least 1 digit }*/
/* < E | e < - | + > { at least 1 digit } >*/
cfloat *number;
char saved;
saved = *bend;
if( saved != NULLCHAR ) {
*bend = NULLCHAR; /* KLUGE!!!*/
}
number = CFAlloc( bend - bstart );
DoConvert( number, bstart );
if( saved != NULLCHAR ) {
*bend = saved; /* un-KLUGE*/
}
return( number );
}
extern cfloat *CFCopy( cfloat *old ) {
/***************************************/
cfloat *new;
new = CFAlloc( old->len );
memcpy( new, old, offsetof( cfloat, mant ) + old->len + 1 );
return( new );
}
extern cfloat *CFTrunc( cfloat *f ) {
/*************************************/
cfloat *new;
int len;
len = f->exp;
if( len <= 0 ) return( CFAlloc( 1 ) );
new = CFCopy( f );
if( new->len <= len ) return( new );
new->len = len;
new->mant[ len ] = NULLCHAR;
return( new );
}
extern cfloat *CFRound( cfloat *f ) {
/*************************************/
cfloat *trim;
cfloat *addto;
cfloat *new;
int len;
len = f->exp;
if( len < 0 ) return( CFAlloc( 1 ) );
if( f->len <= len ) return( CFCopy( f ) );
trim = CFTrunc( f );
if( f->mant[ len ] < '5' ) return( trim );
if( f->sign < 0 && f->len == ( len + 1 ) ) return( trim );
addto = CFAlloc( 1 );
addto->sign = f->sign;
addto->mant[0] = '1';
new = CFAdd( trim, addto );
CFFree( trim );
CFFree( addto );
return( new );
}
static cfloat *CFCnvLongToF( signed_32 data, cf_bool is_signed ) {
/******************************************************************/
cfloat *new;
int len;
signed_8 sign;
char *digit;
unsigned_32 dividend;
char mant[I32DIGITS+1];
if( data == 0 ) return( CFAlloc( 0 ) );
if( is_signed != CF_FALSE && -data == data ) {
/* Aha! It's -MaxNegI32 */
new = CFCopy( (cfloat *)&MaxNegI32 );
new->sign = -1;
return( new );
}
sign = 1;
if( data < 0 && is_signed ) {
data = -data;
sign = -1;
}
len = 0;
digit = &mant[ I32DIGITS ];
*digit = NULLCHAR;
dividend = data;
while( dividend != 0 ) {
*--digit = U32ModDiv( ÷nd, 10 ) + '0';
++len;
}
if( len > I16DIGITS ) {
new = CFAlloc( I32DIGITS );
} else {
new = CFAlloc( I16DIGITS );
}
memcpy( new->mant, digit, len + 1 );
new->sign = sign;
new->exp = len;
new->len = len;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?