diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/windbg/lib | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/windbg/lib')
-rw-r--r-- | private/windbg/lib/assrt.c | 31 | ||||
-rw-r--r-- | private/windbg/lib/atold.c | 54 | ||||
-rw-r--r-- | private/windbg/lib/cfin.c | 73 | ||||
-rw-r--r-- | private/windbg/lib/cfout.c | 132 | ||||
-rw-r--r-- | private/windbg/lib/constpow.c | 161 | ||||
-rw-r--r-- | private/windbg/lib/cv.h | 518 | ||||
-rw-r--r-- | private/windbg/lib/cvt.c | 768 | ||||
-rw-r--r-- | private/windbg/lib/heap.c | 106 | ||||
-rw-r--r-- | private/windbg/lib/intrncvt.c | 703 | ||||
-rw-r--r-- | private/windbg/lib/makefile | 6 | ||||
-rw-r--r-- | private/windbg/lib/mantold.c | 184 | ||||
-rw-r--r-- | private/windbg/lib/rtlproto.h | 88 | ||||
-rw-r--r-- | private/windbg/lib/sources | 48 | ||||
-rw-r--r-- | private/windbg/lib/strgtold.c | 393 | ||||
-rw-r--r-- | private/windbg/lib/strtoli.c | 242 | ||||
-rw-r--r-- | private/windbg/lib/tenpow.c | 240 | ||||
-rw-r--r-- | private/windbg/lib/x10fout.c | 464 |
17 files changed, 4211 insertions, 0 deletions
diff --git a/private/windbg/lib/assrt.c b/private/windbg/lib/assrt.c new file mode 100644 index 000000000..945793461 --- /dev/null +++ b/private/windbg/lib/assrt.c @@ -0,0 +1,31 @@ +/*** +*assrt.c - assertions needed for string conversion routines +* +* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Make sure that the data types used by the string conversion +* routines have the right size. If this file does not compile, +* the type definitions in cv.h should change appropriately. +* +*Revision History: +* 07-25-91 GDP written +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + + +#include "cv.h" + +static void assertion_test(void) +{ + sizeof(u_char) == 1 ? 0 : 1/0, + sizeof(u_short) == 2 ? 0 : 1/0, + sizeof(u_long) == 4 ? 0 : 1/0, + sizeof(s_char) == 1 ? 0 : 1/0, + sizeof(s_short) == 2 ? 0 : 1/0, + sizeof(s_long) == 4 ? 0 : 1/0; +#ifdef _ULDSUPPORT + sizeof(long double) == 10 ? 0 : 1/0; +#endif +} diff --git a/private/windbg/lib/atold.c b/private/windbg/lib/atold.c new file mode 100644 index 000000000..fa9e035a4 --- /dev/null +++ b/private/windbg/lib/atold.c @@ -0,0 +1,54 @@ +/*** +*atold.c - convert char string to long double +* +* Copyright (c) 1989-1989, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Converts a character string into a long double. +* +*Revision History: +* 03-09-89 WAJ Initial version. +* 06-05-89 WAJ Made changes for C6 compiler. +* 05-17-91 WAJ Now uses long double. +* 07-22-91 GDP Now uses _ULDOUBLE so that it can be used +* even if 'long double' is not supported. +* It also uses the C version of __strgtold() +* 04-30-92 GDP Now calls _atoldbl +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + +#include "cv.h" + + + +/*** +*_ULDOUBLE _atold( char * string ) - convert string to a long double +* +*Purpose: +* _atold() recognizes an optional string of whitespace, then +* an optional sign, then a string of digits optionally +* containing a decimal point, then an optional e or E followed +* by an optionally signed integer, and converts all this to +* to a long double. The first unrecognized character ends the string. +* +*Entry: +* string - pointer to string to convert +* +*Exit: +* returns long double value of character representation +* +*Exceptions: +* +*******************************************************************************/ + + +_ULDOUBLE _atold(char * string ) +{ + _ULDOUBLE x; + + _atoldbl( (_ULDOUBLE *)&x, string); + + return( x ); +} + diff --git a/private/windbg/lib/cfin.c b/private/windbg/lib/cfin.c new file mode 100644 index 000000000..15582de0b --- /dev/null +++ b/private/windbg/lib/cfin.c @@ -0,0 +1,73 @@ +/*** +*cfin.c - Encode interface for C +* +* Copyright (c) 19xx-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* 07-20-91 GDP Ported to C from assembly +* 04-30-92 GDP use __strgtold12 and _ld12tod +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + +#include <string.h> +#include "cv.h" + + + + +#ifndef MTHREAD +static struct _flt ret; +static FLT flt = &ret; +#endif + +/* The only three conditions that this routine detects */ +#define CFIN_NODIGITS 512 +#define CFIN_OVERFLOW 128 +#define CFIN_UNDERFLOW 256 + +/* This version ignores the last two arguments (radix and scale) + * Input string should be null terminated + * len is also ignored + */ +#ifdef MTHREAD +FLT _fltin2(FLT flt, const char *str, int len_ignore, int scale_ignore, int radix_ignore) +#else +FLT _fltin(const char *str, int len_ignore, int scale_ignore, int radix_ignore) +#endif +{ + _ULDBL12 ld12; + UDOUBLE x; + char *EndPtr; + unsigned flags; + int retflags = 0; + + flags = __strgtold12(&ld12, &EndPtr, (char *)str, 0); + if (flags & SLD_NODIGITS) { + retflags |= CFIN_NODIGITS; + *(u_long *)&x = 0; + *((u_long *)&x+1) = 0; + } + else { + INTRNCVT_STATUS intrncvt; + + intrncvt = _ld12tod(&ld12, &x); + + if (flags & SLD_OVERFLOW || + intrncvt == INTRNCVT_OVERFLOW) { + retflags |= CFIN_OVERFLOW; + } + if (flags & SLD_UNDERFLOW || + intrncvt == INTRNCVT_UNDERFLOW) { + retflags |= CFIN_UNDERFLOW; + } + } + + flt->flags = retflags; + flt->nbytes = EndPtr - (char *)str; + flt->dval = *(double *)&x; + + return flt; +} diff --git a/private/windbg/lib/cfout.c b/private/windbg/lib/cfout.c new file mode 100644 index 000000000..94814be20 --- /dev/null +++ b/private/windbg/lib/cfout.c @@ -0,0 +1,132 @@ +/*** +*cfout.c - Encode interface for C +* +* Copyright (c) 19xx-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* 07-20-91 GDP Ported to C from assembly +* 04-30-92 GDP Added _dtold routine (moved here from ldtod.c) +* 05-14-92 GDP NDIGITS is now 17 (instead of 16) +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + + +#include <string.h> +#include "cv.h" + + + + +#define NDIGITS 17 + +void __dtold(_ULDOUBLE *pld, UDOUBLE *px); + + +#ifndef MTHREAD +static struct _strflt ret; +static FOS fos; +#endif + +#ifdef MTHREAD +STRFLT _fltout2(UDOUBLE x, STRFLT flt, char *resultstr) +{ + _ULDOUBLE ld; + FOS autofos; + + __dtold(&ld, &x); + flt->flag = $I10_OUTPUT(ld,NDIGITS,0,&autofos); + flt->sign = autofos.sign; + flt->decpt = autofos.exp; + strcpy(resultstr,autofos.man); + flt->mantissa = resultstr; + + return flt; +} + +#else + +STRFLT _fltout(UDOUBLE x) +{ + _ULDOUBLE ld; + + __dtold(&ld, &x); + ret.flag = $I10_OUTPUT(ld,NDIGITS,0,&fos); + ret.sign = fos.sign; + ret.decpt = fos.exp; + ret.mantissa = fos.man; + + return &ret; +} + +#endif + + + + +/*** +* __dtold - convert a double into a _ULDOUBLE +* +*Purpose: Use together with i10_output() to get string conversion +* for double +* +*Entry: double *px +* +*Exit: the corresponding _ULDOUBLE value is returned in *pld +* +*Exceptions: +* +*******************************************************************************/ + +void __dtold(_ULDOUBLE *pld, UDOUBLE *px) +{ + u_short exp; + u_short sign; + u_long manhi, manlo; + u_long msb = MSB_ULONG; + u_short ldexp = 0; + + exp = (*U_SHORT4_D(px) & (u_short)0x7ff0) >> 4; + sign = *U_SHORT4_D(px) & (u_short)0x8000; + manhi = *UL_HI_D(px) & 0xfffff; + manlo = *UL_LO_D(px); + + switch (exp) { + case D_MAXEXP: + ldexp = LD_MAXEXP; + break; + case 0: + /* check for zero */ + if (manhi == 0 && manlo == 0) { + *UL_MANHI_LD(pld) = 0; + *UL_MANLO_LD(pld) = 0; + *U_EXP_LD(pld) = 0; + return; + } + /* we have a denormal -- we'll normalize later */ + ldexp = (u_short) ((s_short)exp - D_BIAS + LD_BIAS + 1); + msb = 0; + break; + default: + exp -= D_BIAS; + ldexp = (u_short) ((s_short)exp + LD_BIAS); + break; + } + + *UL_MANHI_LD(pld) = msb | manhi << 11 | manlo >> 21; + *UL_MANLO_LD(pld) = manlo << 11; + + /* normalize if necessary */ + while ((*UL_MANHI_LD(pld) & MSB_ULONG) == 0) { + /* shift left */ + *UL_MANHI_LD(pld) = *UL_MANHI_LD(pld) << 1 | + (MSB_ULONG & *UL_MANLO_LD(pld) ? 1: 0); + (*UL_MANLO_LD(pld)) <<= 1; + ldexp --; + } + + *U_EXP_LD(pld) = sign | ldexp; + +} diff --git a/private/windbg/lib/constpow.c b/private/windbg/lib/constpow.c new file mode 100644 index 000000000..d8fb3156c --- /dev/null +++ b/private/windbg/lib/constpow.c @@ -0,0 +1,161 @@ +/*** +*constpow.c - constant powers of ten +* +* Copyright (c) 19xx-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Provide powers of ten in long double form: +* 10^(2^i), i=0,1,2,... +* +*Revision History: +* 7-17-91 GDP Initial version (ported from assembly) +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + + +#include "cv.h" + + + +/* Format: A 10 byte long double + 2 bytes of extra precision + * If the extra precision is desired, the 10-byte long double + * should be "unrounded" first. + * This may change in later versions + */ + +#ifdef L_END + +_ULDBL12 _pow10pos[] = { + /*P0001*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0x02,0x40}}, + /*P0002*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x05,0x40}}, + /*P0003*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFA,0x08,0x40}}, + /*P0004*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9C,0x0C,0x40}}, + /*P0005*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xC3,0x0F,0x40}}, + /*P0006*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xF4,0x12,0x40}}, + /*P0007*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x80,0x96,0x98,0x16,0x40}}, + /*P0008*/ {{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x20,0xBC,0xBE,0x19,0x40}}, + /*P0016*/ {{0x00,0x00, 0x00,0x00,0x00,0x04,0xBF,0xC9,0x1B,0x8E,0x34,0x40}}, + /*P0024*/ {{0x00,0x00, 0x00,0xA1,0xED,0xCC,0xCE,0x1B,0xC2,0xD3,0x4E,0x40}}, + /*P0032*/ {{0x20,0xF0, 0x9E,0xB5,0x70,0x2B,0xA8,0xAD,0xC5,0x9D,0x69,0x40}}, + /*P0040*/ {{0xD0,0x5D, 0xFD,0x25,0xE5,0x1A,0x8E,0x4F,0x19,0xEB,0x83,0x40}}, + /*P0048*/ {{0x71,0x96, 0xD7,0x95,0x43,0x0E,0x05,0x8D,0x29,0xAF,0x9E,0x40}}, + /*P0056*/ {{0xF9,0xBF, 0xA0,0x44,0xED,0x81,0x12,0x8F,0x81,0x82,0xB9,0x40}}, + /*P0064*/ {{0xBF,0x3C, 0xD5,0xA6,0xCF,0xFF,0x49,0x1F,0x78,0xC2,0xD3,0x40}}, + /*P0128*/ {{0x6F,0xC6, 0xE0,0x8C,0xE9,0x80,0xC9,0x47,0xBA,0x93,0xA8,0x41}}, + /*P0192*/ {{0xBC,0x85, 0x6B,0x55,0x27,0x39,0x8D,0xF7,0x70,0xE0,0x7C,0x42}}, + /*P0256*/ {{0xBC,0xDD, 0x8E,0xDE,0xF9,0x9D,0xFB,0xEB,0x7E,0xAA,0x51,0x43}}, + /*P0320*/ {{0xA1,0xE6, 0x76,0xE3,0xCC,0xF2,0x29,0x2F,0x84,0x81,0x26,0x44}}, + /*P0384*/ {{0x28,0x10, 0x17,0xAA,0xF8,0xAE,0x10,0xE3,0xC5,0xC4,0xFA,0x44}}, + /*P0448*/ {{0xEB,0xA7, 0xD4,0xF3,0xF7,0xEB,0xE1,0x4A,0x7A,0x95,0xCF,0x45}}, + /*P0512*/ {{0x65,0xCC, 0xC7,0x91,0x0E,0xA6,0xAE,0xA0,0x19,0xE3,0xA3,0x46}}, + /*P1024*/ {{0x0D,0x65, 0x17,0x0C,0x75,0x81,0x86,0x75,0x76,0xC9,0x48,0x4D}}, + /*P1536*/ {{0x58,0x42, 0xE4,0xA7,0x93,0x39,0x3B,0x35,0xB8,0xB2,0xED,0x53}}, + /*P2048*/ {{0x4D,0xA7, 0xE5,0x5D,0x3D,0xC5,0x5D,0x3B,0x8B,0x9E,0x92,0x5A}}, + /*P2560*/ {{0xFF,0x5D, 0xA6,0xF0,0xA1,0x20,0xC0,0x54,0xA5,0x8C,0x37,0x61}}, + /*P3072*/ {{0xD1,0xFD, 0x8B,0x5A,0x8B,0xD8,0x25,0x5D,0x89,0xF9,0xDB,0x67}}, + /*P3584*/ {{0xAA,0x95, 0xF8,0xF3,0x27,0xBF,0xA2,0xC8,0x5D,0xDD,0x80,0x6E}}, + /*P4096*/ {{0x4C,0xC9, 0x9B,0x97,0x20,0x8A,0x02,0x52,0x60,0xC4,0x25,0x75}} +}; + +_ULDBL12 _pow10neg[] = { + /*N0001*/ {{0xCD,0xCC, 0xCD,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFB,0x3F}}, + /*N0002*/ {{0x71,0x3D, 0x0A,0xD7,0xA3,0x70,0x3D,0x0A,0xD7,0xA3,0xF8,0x3F}}, + /*N0003*/ {{0x5A,0x64, 0x3B,0xDF,0x4F,0x8D,0x97,0x6E,0x12,0x83,0xF5,0x3F}}, + /*N0004*/ {{0xC3,0xD3, 0x2C,0x65,0x19,0xE2,0x58,0x17,0xB7,0xD1,0xF1,0x3F}}, + /*N0005*/ {{0xD0,0x0F, 0x23,0x84,0x47,0x1B,0x47,0xAC,0xC5,0xA7,0xEE,0x3F}}, + /*N0006*/ {{0x40,0xA6, 0xB6,0x69,0x6C,0xAF,0x05,0xBD,0x37,0x86,0xEB,0x3F}}, + /*N0007*/ {{0x33,0x3D, 0xBC,0x42,0x7A,0xE5,0xD5,0x94,0xBF,0xD6,0xE7,0x3F}}, + /*N0008*/ {{0xC2,0xFD, 0xFD,0xCE,0x61,0x84,0x11,0x77,0xCC,0xAB,0xE4,0x3F}}, + /*N0016*/ {{0x2F,0x4C, 0x5B,0xE1,0x4D,0xC4,0xBE,0x94,0x95,0xE6,0xC9,0x3F}}, + /*N0024*/ {{0x92,0xC4, 0x53,0x3B,0x75,0x44,0xCD,0x14,0xBE,0x9A,0xAF,0x3F}}, + /*N0032*/ {{0xDE,0x67, 0xBA,0x94,0x39,0x45,0xAD,0x1E,0xB1,0xCF,0x94,0x3F}}, + /*N0040*/ {{0x24,0x23, 0xC6,0xE2,0xBC,0xBA,0x3B,0x31,0x61,0x8B,0x7A,0x3F}}, + /*N0048*/ {{0x61,0x55, 0x59,0xC1,0x7E,0xB1,0x53,0x7C,0x12,0xBB,0x5F,0x3F}}, + /*N0056*/ {{0xD7,0xEE, 0x2F,0x8D,0x06,0xBE,0x92,0x85,0x15,0xFB,0x44,0x3F}}, + /*N0064*/ {{0x24,0x3F, 0xA5,0xE9,0x39,0xA5,0x27,0xEA,0x7F,0xA8,0x2A,0x3F}}, + /*N0128*/ {{0x7D,0xAC, 0xA1,0xE4,0xBC,0x64,0x7C,0x46,0xD0,0xDD,0x55,0x3E}}, + /*N0192*/ {{0x63,0x7B, 0x06,0xCC,0x23,0x54,0x77,0x83,0xFF,0x91,0x81,0x3D}}, + /*N0256*/ {{0x91,0xFA, 0x3A,0x19,0x7A,0x63,0x25,0x43,0x31,0xC0,0xAC,0x3C}}, + /*N0320*/ {{0x21,0x89, 0xD1,0x38,0x82,0x47,0x97,0xB8,0x00,0xFD,0xD7,0x3B}}, + /*N0384*/ {{0xDC,0x88, 0x58,0x08,0x1B,0xB1,0xE8,0xE3,0x86,0xA6,0x03,0x3B}}, + /*N0448*/ {{0xC6,0x84, 0x45,0x42,0x07,0xB6,0x99,0x75,0x37,0xDB,0x2E,0x3A}}, + /*N0512*/ {{0x33,0x71, 0x1C,0xD2,0x23,0xDB,0x32,0xEE,0x49,0x90,0x5A,0x39}}, + /*N1024*/ {{0xA6,0x87, 0xBE,0xC0,0x57,0xDA,0xA5,0x82,0xA6,0xA2,0xB5,0x32}}, + /*N1536*/ {{0xE2,0x68, 0xB2,0x11,0xA7,0x52,0x9F,0x44,0x59,0xB7,0x10,0x2C}}, + /*N2048*/ {{0x25,0x49, 0xE4,0x2D,0x36,0x34,0x4F,0x53,0xAE,0xCE,0x6B,0x25}}, + /*N2560*/ {{0x8F,0x59, 0x04,0xA4,0xC0,0xDE,0xC2,0x7D,0xFB,0xE8,0xC6,0x1E}}, + /*N3072*/ {{0x9E,0xE7, 0x88,0x5A,0x57,0x91,0x3C,0xBF,0x50,0x83,0x22,0x18}}, + /*N3584*/ {{0x4E,0x4B, 0x65,0x62,0xFD,0x83,0x8F,0xAF,0x06,0x94,0x7D,0x11}}, + /*N4096*/ {{0xE4,0x2D, 0xDE,0x9F,0xCE,0xD2,0xC8,0x04,0xDD,0xA6,0xD8,0x0A}} +}; + +#endif + +#ifdef B_END + +_ULDBL12 _pow10pos[] = { + /*P0001*/ {{0x40,0x02,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0002*/ {{0x40,0x05,0xC8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0003*/ {{0x40,0x08,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0004*/ {{0x40,0x0C,0x9C,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0005*/ {{0x40,0x0F,0xC3,0x50,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0006*/ {{0x40,0x12,0xF4,0x24,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0007*/ {{0x40,0x16,0x98,0x96,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0008*/ {{0x40,0x19,0xBE,0xBC,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, + /*P0016*/ {{0x40,0x34,0x8E,0x1B,0xC9,0xBF,0x04,0x00,0x00,0x00, 0x00,0x00}}, + /*P0024*/ {{0x40,0x4E,0xD3,0xC2,0x1B,0xCE,0xCC,0xED,0xA1,0x00, 0x00,0x00}}, + /*P0032*/ {{0x40,0x69,0x9D,0xC5,0xAD,0xA8,0x2B,0x70,0xB5,0x9E, 0xF0,0x20}}, + /*P0040*/ {{0x40,0x83,0xEB,0x19,0x4F,0x8E,0x1A,0xE5,0x25,0xFD, 0x5D,0xD0}}, + /*P0048*/ {{0x40,0x9E,0xAF,0x29,0x8D,0x05,0x0E,0x43,0x95,0xD7, 0x96,0x71}}, + /*P0056*/ {{0x40,0xB9,0x82,0x81,0x8F,0x12,0x81,0xED,0x44,0xA0, 0xBF,0xF9}}, + /*P0064*/ {{0x40,0xD3,0xC2,0x78,0x1F,0x49,0xFF,0xCF,0xA6,0xD5, 0x3C,0xBF}}, + /*P0128*/ {{0x41,0xA8,0x93,0xBA,0x47,0xC9,0x80,0xE9,0x8C,0xE0, 0xC6,0x6F}}, + /*P0192*/ {{0x42,0x7C,0xE0,0x70,0xF7,0x8D,0x39,0x27,0x55,0x6B, 0x85,0xBC}}, + /*P0256*/ {{0x43,0x51,0xAA,0x7E,0xEB,0xFB,0x9D,0xF9,0xDE,0x8E, 0xDD,0xBC}}, + /*P0320*/ {{0x44,0x26,0x81,0x84,0x2F,0x29,0xF2,0xCC,0xE3,0x76, 0xE6,0xA1}}, + /*P0384*/ {{0x44,0xFA,0xC4,0xC5,0xE3,0x10,0xAE,0xF8,0xAA,0x17, 0x10,0x28}}, + /*P0448*/ {{0x45,0xCF,0x95,0x7A,0x4A,0xE1,0xEB,0xF7,0xF3,0xD4, 0xA7,0xEB}}, + /*P0512*/ {{0x46,0xA3,0xE3,0x19,0xA0,0xAE,0xA6,0x0E,0x91,0xC7, 0xCC,0x65}}, + /*P1024*/ {{0x4D,0x48,0xC9,0x76,0x75,0x86,0x81,0x75,0x0C,0x17, 0x65,0x0D}}, + /*P1536*/ {{0x53,0xED,0xB2,0xB8,0x35,0x3B,0x39,0x93,0xA7,0xE4, 0x42,0x58}}, + /*P2048*/ {{0x5A,0x92,0x9E,0x8B,0x3B,0x5D,0xC5,0x3D,0x5D,0xE5, 0xA7,0x4D}}, + /*P2560*/ {{0x61,0x37,0x8C,0xA5,0x54,0xC0,0x20,0xA1,0xF0,0xA6, 0x5D,0xFF}}, + /*P3072*/ {{0x67,0xDB,0xF9,0x89,0x5D,0x25,0xD8,0x8B,0x5A,0x8B, 0xFD,0xD1}}, + /*P3584*/ {{0x6E,0x80,0xDD,0x5D,0xC8,0xA2,0xBF,0x27,0xF3,0xF8, 0x95,0xAA}}, + /*P4096*/ {{0x75,0x25,0xC4,0x60,0x52,0x02,0x8A,0x20,0x97,0x9B, 0xC9,0x4C}} +}; + +_ULDBL12 _pow10neg[] = { + /*N0001*/ {{0x3F,0xFB,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCD, 0xCC,0xCD}}, + /*N0002*/ {{0x3F,0xF8,0xA3,0xD7,0x0A,0x3D,0x70,0xA3,0xD7,0x0A, 0x3D,0x71}}, + /*N0003*/ {{0x3F,0xF5,0x83,0x12,0x6E,0x97,0x8D,0x4F,0xDF,0x3B, 0x64,0x5A}}, + /*N0004*/ {{0x3F,0xF1,0xD1,0xB7,0x17,0x58,0xE2,0x19,0x65,0x2C, 0xD3,0xC3}}, + /*N0005*/ {{0x3F,0xEE,0xA7,0xC5,0xAC,0x47,0x1B,0x47,0x84,0x23, 0x0F,0xD0}}, + /*N0006*/ {{0x3F,0xEB,0x86,0x37,0xBD,0x05,0xAF,0x6C,0x69,0xB6, 0xA6,0x40}}, + /*N0007*/ {{0x3F,0xE7,0xD6,0xBF,0x94,0xD5,0xE5,0x7A,0x42,0xBC, 0x3D,0x33}}, + /*N0008*/ {{0x3F,0xE4,0xAB,0xCC,0x77,0x11,0x84,0x61,0xCE,0xFD, 0xFD,0xC2}}, + /*N0016*/ {{0x3F,0xC9,0xE6,0x95,0x94,0xBE,0xC4,0x4D,0xE1,0x5B, 0x4C,0x2F}}, + /*N0024*/ {{0x3F,0xAF,0x9A,0xBE,0x14,0xCD,0x44,0x75,0x3B,0x53, 0xC4,0x92}}, + /*N0032*/ {{0x3F,0x94,0xCF,0xB1,0x1E,0xAD,0x45,0x39,0x94,0xBA, 0x67,0xDE}}, + /*N0040*/ {{0x3F,0x7A,0x8B,0x61,0x31,0x3B,0xBA,0xBC,0xE2,0xC6, 0x23,0x24}}, + /*N0048*/ {{0x3F,0x5F,0xBB,0x12,0x7C,0x53,0xB1,0x7E,0xC1,0x59, 0x55,0x61}}, + /*N0056*/ {{0x3F,0x44,0xFB,0x15,0x85,0x92,0xBE,0x06,0x8D,0x2F, 0xEE,0xD7}}, + /*N0064*/ {{0x3F,0x2A,0xA8,0x7F,0xEA,0x27,0xA5,0x39,0xE9,0xA5, 0x3F,0x24}}, + /*N0128*/ {{0x3E,0x55,0xDD,0xD0,0x46,0x7C,0x64,0xBC,0xE4,0xA1, 0xAC,0x7D}}, + /*N0192*/ {{0x3D,0x81,0x91,0xFF,0x83,0x77,0x54,0x23,0xCC,0x06, 0x7B,0x63}}, + /*N0256*/ {{0x3C,0xAC,0xC0,0x31,0x43,0x25,0x63,0x7A,0x19,0x3A, 0xFA,0x91}}, + /*N0320*/ {{0x3B,0xD7,0xFD,0x00,0xB8,0x97,0x47,0x82,0x38,0xD1, 0x89,0x21}}, + /*N0384*/ {{0x3B,0x03,0xA6,0x86,0xE3,0xE8,0xB1,0x1B,0x08,0x58, 0x88,0xDC}}, + /*N0448*/ {{0x3A,0x2E,0xDB,0x37,0x75,0x99,0xB6,0x07,0x42,0x45, 0x84,0xC6}}, + /*N0512*/ {{0x39,0x5A,0x90,0x49,0xEE,0x32,0xDB,0x23,0xD2,0x1C, 0x71,0x33}}, + /*N1024*/ {{0x32,0xB5,0xA2,0xA6,0x82,0xA5,0xDA,0x57,0xC0,0xBE, 0x87,0xA6}}, + /*N1536*/ {{0x2C,0x10,0xB7,0x59,0x44,0x9F,0x52,0xA7,0x11,0xB2, 0x68,0xE2}}, + /*N2048*/ {{0x25,0x6B,0xCE,0xAE,0x53,0x4F,0x34,0x36,0x2D,0xE4, 0x49,0x25}}, + /*N2560*/ {{0x1E,0xC6,0xE8,0xFB,0x7D,0xC2,0xDE,0xC0,0xA4,0x04, 0x59,0x8F}}, + /*N3072*/ {{0x18,0x22,0x83,0x50,0xBF,0x3C,0x91,0x57,0x5A,0x88, 0xE7,0x9E}}, + /*N3584*/ {{0x11,0x7D,0x94,0x06,0xAF,0x8F,0x83,0xFD,0x62,0x65, 0x4B,0x4E}}, + /*N4096*/ {{0x0A,0xD8,0xA6,0xDD,0x04,0xC8,0xD2,0xCE,0x9F,0xDE, 0x2D,0xE4}} +}; + +#endif diff --git a/private/windbg/lib/cv.h b/private/windbg/lib/cv.h new file mode 100644 index 000000000..2650c9628 --- /dev/null +++ b/private/windbg/lib/cv.h @@ -0,0 +1,518 @@ +/*** +*cv.h - definitions for floating point conversion +* +* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* define types, macros, and constants used in floating point +* conversion routines +* +*Revision History: +* 7-17-91 GDP initial version +* 9-21-91 GDP restructured 'ifdef' directives +* 10-29-91 GDP MIPS port: new defs for ALIGN and UDOUBLE +* 3-03-92 GDP removed os2 16-bit stuff +* 4-30-92 GDP support intrncvt.c --cleanup and reorganize +* +*******************************************************************************/ +#ifndef _INC_CV + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _WINDOWS_ // NOTENOTE Davegi This needs to be cleaned up! +typedef float FLOAT; +#endif // _WINDOWS_ + +// #include <cruntime.h> + +#ifndef _MIPS_ +#if (_MSC_VER <= 600) +#define __cdecl _cdecl +#endif +#endif + + +// +// For MIPS, define UDOUBLE as 'double' before including fltintrn.h, +// so that the definition in fltintrn.h is not used. +// This is done because floating point arguments are passed in the +// fp register. +// + +#ifdef MIPS +#define UDOUBLE double +#endif + +// +// definitions from crt32\h\fltintrn.h -- keep in sync +// + + +/* + * structs used to fool the compiler into not generating floating point + * instructions when copying and pushing [long] double values + */ + +#ifndef UDOUBLE + +typedef struct { + double x; +} UDOUBLE; + +#endif + + +/* + * typedef for _fltout + */ + +typedef struct _strflt +{ + int sign; /* zero if positive otherwise negative */ + int decpt; /* exponent of floating point number */ + int flag; /* zero if okay otherwise IEEE overflow */ + char *mantissa; /* pointer to mantissa in string form */ +} + *STRFLT; + + +/* + * typedef for _fltin + */ + +typedef struct _flt +{ + int flags; + int nbytes; /* number of characters read */ + long lval; + double dval; /* the returned floating point number */ +} + *FLT; + + +char *_cftoe(double *, char *, int, int); +char *_cftof(double *, char *, int); +void _fptostr(char *, int, STRFLT); + +#ifdef MTHREAD + +STRFLT _fltout2( double, STRFLT, char * ); +FLT _fltin2( FLT , const char *, int, int, int ); + +#else + +STRFLT _fltout( UDOUBLE ); +FLT _fltin( const char *, int, int, int ); + +#endif + + +// +// end of definitions from crt32\h\fltintrn.h +// + + + +/* define little endian or big endian memory */ + +#ifdef i386 +#define L_END +#endif + +#ifdef MIPS +#define L_END +#endif + +#ifdef ALPHA +#define L_END +#endif + +#ifdef PPC +#define L_END +#endif + +typedef unsigned char u_char; /* should have 1 byte */ +typedef char s_char; /* should have 1 byte */ +typedef unsigned short u_short; /* should have 2 bytes */ +typedef signed short s_short; /* should have 2 bytes */ +typedef unsigned int u_long; /* sholuld have 4 bytes */ +typedef int s_long; /* sholuld have 4 bytes */ + + +// +// defining _LDSUPPORT enables using long double computations +// for string conversion. We do not do this even for i386, +// since we want to avoid using floating point code that +// may generate IEEE exceptions. +// +// Currently our string conversion routines do not conform +// to the special requirements of the IEEE standard for +// floating point conversions +// + + +#ifndef _LDSUPPORT + +#pragma pack(4) +typedef struct { + u_char ld[10]; +} _ULDOUBLE; +#pragma pack() + +#define PTR_LD(x) ((u_char *)(&(x)->ld)) + +#else + +typedef long double _ULDOUBLE; + +#define PTR_LD(x) ((u_char *)(x)) + +#endif + + +#pragma pack(4) +typedef struct { + u_char ld12[12]; +} _ULDBL12; +#pragma pack() + +#if 0 +typedef struct { + float f; +} FLOAT; +#endif + + + +// +// return values for internal conversion routines +// (12-byte to long double, double, or float) +// + +typedef enum { + INTRNCVT_OK, + INTRNCVT_OVERFLOW, + INTRNCVT_UNDERFLOW +} INTRNCVT_STATUS; + + +// +// return values for strgtold12 routine +// + +#define SLD_UNDERFLOW 1 +#define SLD_OVERFLOW 2 +#define SLD_NODIGITS 4 + +#define MAX_MAN_DIGITS 21 + + +// specifies '%f' format + +#define SO_FFORMAT 1 + +typedef struct _FloatOutStruct { + short exp; + char sign; + char ManLen; + char man[MAX_MAN_DIGITS+1]; + } FOS; + + + +#define PTR_12(x) ((u_char *)(&(x)->ld12)) + +#define MAX_USHORT ((u_short)0xffff) +#define MSB_USHORT ((u_short)0x8000) +#define MAX_ULONG ((u_long)0xffffffff) +#define MSB_ULONG ((u_long)0x80000000) + +#define TMAX10 5200 /* maximum temporary decimal exponent */ +#define TMIN10 -5200 /* minimum temporary decimal exponent */ +#define LD_MAX_EXP_LEN 4 /* maximum number of decimal exponent digits */ +#define LD_MAX_MAN_LEN 24 /* maximum length of mantissa (decimal)*/ +#define LD_MAX_MAN_LEN1 25 /* MAX_MAN_LEN+1 */ + +#define LD_BIAS 0x3fff /* exponent bias for long double */ +#define LD_BIASM1 0x3ffe /* LD_BIAS - 1 */ +#define LD_MAXEXP 0x7fff /* maximum biased exponent */ + +#define D_BIAS 0x3ff /* exponent bias for double */ +#define D_BIASM1 0x3fe /* D_BIAS - 1 */ +#define D_MAXEXP 0x7ff /* maximum biased exponent */ + + + +/* Recognizing special patterns in the mantissa field */ +#define _EXP_SP 0x7fff +#define NAN_BIT (1<<30) + +#define _IS_MAN_INF(signbit, manhi, manlo) \ + ( (manhi)==MSB_ULONG && (manlo)==0x0 ) + + +#ifdef i386 +#define _IS_MAN_IND(signbit, manhi, manlo) \ + ((signbit) && (manhi)==0xc0000000 && (manlo)==0) + +#define _IS_MAN_QNAN(signbit, manhi, manlo) \ + ( (manhi)&NAN_BIT ) + +#define _IS_MAN_SNAN(signbit, manhi, manlo) \ + (!( _IS_MAN_INF(signbit, manhi, manlo) || \ + _IS_MAN_QNAN(signbit, manhi, manlo) )) + + +#else +#ifdef MIPS +#define _IS_MAN_IND(signbit, manhi, manlo) \ + (!(signbit) && (manhi)==0xbfffffff && (manlo)==0xfffff800) + +#define _IS_MAN_SNAN(signbit, manhi, manlo) \ + ( (manhi)&NAN_BIT ) + +#define _IS_MAN_QNAN(signbit, manhi, manlo) \ + (!( _IS_MAN_INF(signbit, manhi, manlo) || \ + _IS_MAN_SNAN(signbit, manhi, manlo) )) +#else +#ifdef PPC +// copied alpha crap below bugbug fmbutt +#define _IS_MAN_IND(signbit, manhi, manlo) 1 +#define _IS_MAN_SNAN(signbit, manhi, manlo) 1 +#define _IS_MAN_QNAN(signbit, manhi, manlo) 1 +#else // ALPHA +// MBH - bugbug - just put anything in here because its +// only used to determine string size! +// +#define _IS_MAN_IND(signbit, manhi, manlo) 1 +#define _IS_MAN_SNAN(signbit, manhi, manlo) 1 +#define _IS_MAN_QNAN(signbit, manhi, manlo) 1 +#endif +#endif +#endif + + +// +// MBH -bugbug +// We probaby don't look just like 386 in this regard. +// Figure out ALPHA stuff for FP here. +// + +#if defined (L_END) && !defined (MIPS) +/* "little endian" memory */ +/* Note: MIPS has alignment requirements and has different macros */ +/* + * Manipulation of a 12-byte long double number (an ordinary + * 10-byte long double plus two extra bytes of mantissa). + */ + +/* a pointer to the exponent/sign portion */ +#define U_EXP_12(p) ((u_short *)(PTR_12(p)+10)) + +/* a pointer to the 4 hi-order bytes of the mantissa */ +#define UL_MANHI_12(p) ((u_long *)(PTR_12(p)+6)) + +/* a pointer to the 4 lo-order bytes of the ordinary (8-byte) mantissa */ +#define UL_MANLO_12(p) ((u_long *)(PTR_12(p)+2)) + +/* a pointer to the 2 extra bytes of the mantissa */ +#define U_XT_12(p) ((u_short *)PTR_12(p)) + +/* a pointer to the 4 lo-order bytes of the extended (10-byte) mantissa */ +#define UL_LO_12(p) ((u_long *)PTR_12(p)) + +/* a pointer to the 4 mid-order bytes of the extended (10-byte) mantissa */ +#define UL_MED_12(p) ((u_long *)(PTR_12(p)+4)) + +/* a pointer to the 4 hi-order bytes of the extended long double */ +#define UL_HI_12(p) ((u_long *)(PTR_12(p)+8)) + +/* a pointer to the byte of order i (LSB=0, MSB=9)*/ +#define UCHAR_12(p,i) ((u_char *)PTR_12(p)+(i)) + +/* a pointer to a u_short with offset i */ +#define USHORT_12(p,i) ((u_short *)((u_char *)PTR_12(p)+(i))) + +/* a pointer to a u_long with offset i */ +#define ULONG_12(p,i) ((u_long *)((u_char *)PTR_12(p)+(i))) + +/* a pointer to the 10 MSBytes of a 12-byte long double */ +#define TEN_BYTE_PART(p) ((u_char *)PTR_12(p)+2) + +/* + * Manipulation of a 10-byte long double number + */ +#define U_EXP_LD(p) ((u_short *)(PTR_LD(p)+8)) +#define UL_MANHI_LD(p) ((u_long *)(PTR_LD(p)+4)) +#define UL_MANLO_LD(p) ((u_long *)PTR_LD(p)) + +/* + * Manipulation of a 64bit IEEE double + */ +#define U_SHORT4_D(p) ((u_short *)(p) + 3) +#define UL_HI_D(p) ((u_long *)(p) + 1) +#define UL_LO_D(p) ((u_long *)(p)) + +#endif + +#ifdef B_END /* big endian */ + +#define U_EXP_12(p) ((u_short *)PTR_12(p)) +#define UL_MANHI_12(p) ((u_long *)(PTR_12(p)+2)) +#define UL_MANLO_12(p) ((u_long *)(PTR_12(p)+6)) +#define U_XT_12(p) ((u_short *)(PTR_12(p)+10)) + +#define UL_LO_12(p) ((u_long *)PTR_12(p)) +#define UL_MED_12(p) ((u_long *)(PTR_12(p)+4)) +#define UL_HI_12(p) ((u_long *)(PTR_12(p)+8)) + +#define UCHAR_12(p,i) ((u_char *)PTR_12(p)+(11-(i))) +#define USHORT_12(p,i) ((u_short *)((u_char *)PTR_12(p)+10-(i))) +#define ULONG_12(p,i) ((u_long *)((u_char *)PTR_12(p)+8-(i))) +#define TEN_BYTE_PART(p) (u_char *)PTR_12(p) + +#define U_EXP_LD(p) ((u_short *)PTR_LD(p)) +#define UL_MANHI_LD(p) ((u_long *)(PTR_LD(p)+4)) +#define UL_MANLO_LD(p) ((u_long *)(PTR_LD(p)+8)) + +/* + * Manipulation of a 64bit IEEE double + */ +#define U_SHORT4_D(p) ((u_short *)(p) + 3) +#define UL_HI_D(p) ((u_long *)(p) + 1) +#define UL_LO_D(p) ((u_long *)(p)) + +#endif + +#ifdef MIPS + +#define MIPSALIGN(x) ( (unsigned long __unaligned *) (x)) + +#define U_EXP_12(p) ((u_short *)(PTR_12(p)+10)) + +#define UL_MANHI_12(p) ((u_long __unaligned *) (PTR_12(p)+6) ) +#define UL_MANLO_12(p) ((u_long __unaligned *) (PTR_12(p)+2) ) + + +#define U_XT_12(p) ((u_short *)PTR_12(p)) +#define UL_LO_12(p) ((u_long *)PTR_12(p)) +#define UL_MED_12(p) ((u_long *)(PTR_12(p)+4)) +#define UL_HI_12(p) ((u_long *)(PTR_12(p)+8)) + +/* the following 3 macros do not take care of proper alignment */ +#define UCHAR_12(p,i) ((u_char *)PTR_12(p)+(i)) +#define USHORT_12(p,i) ((u_short *)((u_char *)PTR_12(p)+(i))) +#define ULONG_12(p,i) ((u_long *) ((u_char *)PTR_12(p)+(i) )) + +#define TEN_BYTE_PART(p) ((u_char *)PTR_12(p)+2) + +/* + * Manipulation of a 10-byte long double number + */ +#define U_EXP_LD(p) ((u_short *)(PTR_LD(p)+8)) + +#define UL_MANHI_LD(p) ((u_long *) (PTR_LD(p)+4) ) +#define UL_MANLO_LD(p) ((u_long *) PTR_LD(p) ) + +/* + * Manipulation of a 64bit IEEE double + */ +#define U_SHORT4_D(p) ((u_short *)(p) + 3) +#define UL_HI_D(p) ((u_long *)(p) + 1) +#define UL_LO_D(p) ((u_long *)(p)) + +#endif + + +#define PUT_INF_12(p,sign) \ + *UL_HI_12(p) = (sign)?0xffff8000:0x7fff8000; \ + *UL_MED_12(p) = 0; \ + *UL_LO_12(p) = 0; + +#define PUT_ZERO_12(p) *UL_HI_12(p) = 0; \ + *UL_MED_12(p) = 0; \ + *UL_LO_12(p) = 0; + +#define ISZERO_12(p) ((*UL_HI_12(p)&0x7fffffff) == 0 && \ + *UL_MED_12(p) == 0 && \ + *UL_LO_12(p) == 0 ) + +#define PUT_INF_LD(p,sign) \ + *U_EXP_LD(p) = (sign)?0xffff:0x7fff; \ + *UL_MANHI_LD(p) = 0x8000; \ + *UL_MANLO_LD(p) = 0; + +#define PUT_ZERO_LD(p) *U_EXP_LD(p) = 0; \ + *UL_MANHI_LD(p) = 0; \ + *UL_MANLO_LD(p) = 0; + +#define ISZERO_LD(p) ((*U_EXP_LD(p)&0x7fff) == 0 && \ + *UL_MANHI_LD(p) == 0 && \ + *UL_MANLO_LD(p) == 0 ) + + +/********************************************************* + * + * Function Prototypes + * + *********************************************************/ + +/* from mantold.c */ +void __mtold12(char *manptr, unsigned manlen,_ULDBL12 *ld12); +int __addl(u_long x, u_long y, u_long *sum); +void __shl_12(_ULDBL12 *ld12); +void __shr_12(_ULDBL12 *ld12); +void __add_12(_ULDBL12 *x, _ULDBL12 *y); + +/* from tenpow.c */ +void __multtenpow12(_ULDBL12 *pld12,int pow, unsigned mult12); +void __ld12mul(_ULDBL12 *px, _ULDBL12 *py); + +/* from strgtold.c */ +unsigned int __strgtold12(_ULDBL12 *pld12, + char * *p_end_ptr, + char *str, + int mult12); + + +/* from x10fout.c */ + +char * _uldtoa (_ULDOUBLE *px, int maxchars, char *ldtext); + + + +/* this is defined as void in convert.h + * After porting the asm files to c, we need a return value for + * i10_output, that used to reside in reg. ax + */ +int $I10_OUTPUT(_ULDOUBLE ld, int ndigits, + unsigned output_flags, FOS *fos); + + +/* for cvt.c and fltused.c */ +void _cfltcvt(double *arg, char *buffer, + int format, int precision, + int caps); +void _cropzeros(char *buf); +void _fassign(int flag, char *argument, char *number); +void _forcdecpt(char *buf); +int _positive(double *arg); + +/* from intrncvt.c */ +void _atodbl(UDOUBLE *d, char *str); +void _atoldbl(_ULDOUBLE *ld, char *str); +void _atoflt(FLOAT *f, char *str); +INTRNCVT_STATUS _ld12tod(_ULDBL12 *ifp, UDOUBLE *d); +INTRNCVT_STATUS _ld12tof(_ULDBL12 *ifp, FLOAT *f); +void _ld12told(_ULDBL12 *ifp, _ULDOUBLE *ld); + + + +#ifdef __cplusplus +} +#endif + +#define _INC_CV +#endif /* _INC_CV */ diff --git a/private/windbg/lib/cvt.c b/private/windbg/lib/cvt.c new file mode 100644 index 000000000..4932f98ea --- /dev/null +++ b/private/windbg/lib/cvt.c @@ -0,0 +1,768 @@ +/*** +*cvt.c - C floating-point output conversions +* +* Copyright (c) 1987-89, Microsoft Corporation +* +*Purpose: +* contains routines for performing %e, %f, and %g output conversions +* for printf, etc. +* +* routines include _cfltcvt(), _cftoe(), _cftof(), _cftog(), _fassign(), +* _positive(), _cropzeros(), _forcdecpt() +* +*Revision History: +* 04-18-84 RN author +* 01-15-87 BCM corrected processing of %g formats (to handle precision +* as the maximum number of signifcant digits displayed) +* 03-24-87 BCM Evaluation Issues: (fccvt.obj version for ?LIBFA) +* ------------------ +* SDS - no problem +* GD/TS : +* char g_fmt = 0; (local, initialized) +* int g_magnitude =0; (local, initialized) +* char g_round_expansion = 0; (local, initialized) +* STRFLT g_pflt; (local, uninitialized) +* other INIT : +* ALTMATH __fpmath() initialization (perhaps) +* TERM - nothing +* 10-22-87 BCM changes for OS/2 Support Library - +* including elimination of g_... static variables +* in favor of stack-based variables & function arguments +* under MTHREAD switch; changed interfaces to _cfto? routines +* 01-15-88 BCM remove IBMC20 switches; use only memmove, not memcpy; +* use just MTHREAD switch, not SS_NEQ_DGROUP +* 06-13-88 WAJ Fixed %.1g processing for small x +* 08-02-88 WAJ Made changes to _fassign() for new input(). +* 03-09-89 WAJ Added some long double support. +* 06-05-89 WAJ Made changes for C6. ULDOUBLE => long double +* 06-12-89 WAJ Renamed this file from cvtn.c to cvt.c +* 11-02-89 WAJ Removed register.h +* 06-28-90 WAJ Removed fars. +* 11-15-90 WAJ Added _cdecl where needed. Also "pascal" => "_pascal". +* 09-12-91 GDP _cdecl=>_CALLTYPE2 _pascal=>_CALLTYPE5 near=>_NEAR +* 04-30-92 GDP Removed floating point code. Instead used S/W routines +* (_atodbl, _atoflt _atoldbl), so that to avoid generation +* of IEEE exceptions from the lib code. +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + + + +#include <ctype.h> +#include <string.h> +#include <math.h> +#include "cv.h" + + +//NOTENOTE the following takes the place of the isdigit() macro +// which does not work for a yet to be determined reason +#define ISADIGIT(x) ((x)>='0' && (x)<='9' ) + + + + +#ifdef i386 +// Uncomment this for enabling 10-byte long double string conversions +#define LONG_DOUBLE +#endif + + +/* this routine resides in the crt32 tree */ +extern void _fptostr(char *buf, int digits, STRFLT pflt); + + +static void _shift( char *s, int dist ); + +#ifdef MTHREAD + static char * _cftoe2( char * buf, int ndec, int caps, STRFLT pflt, char g_fmt ); + static char * _cftof2( char * buf, int ndec, STRFLT pflt, char g_fmt ); + +#else /* not MTHREAD */ + static char * _cftoe_g( double * pvalue, char * buf, int ndec, int caps ); + static char * _cftof_g( double * pvalue, char * buf, int ndec ); +#endif /* not MTHREAD */ + +/*** +*_forcdecpt(buffer) - force a decimal point in floating-point output +*Purpose: +* force a decimal point in floating point output. we are only called if '#' +* flag is given and precision is 0; so we know the number has no '.'. insert +* the '.' and move everybody else back one position, until '\0' seen +* +* side effects: futzes around with the buffer, trying to insert a '.' +* after the initial string of digits. the first char can usually be +* skipped since it will be a digit or a '-'. but in the 0-precision case, +* the number could start with 'e' or 'E', so we'd want the '.' before the +* exponent in that case. +* +*Entry: +* buffer = (char *) pointer to buffer to modify +* +*Exit: +* returns : (void) +* +*Exceptions: +*******************************************************************************/ + +void _forcdecpt( char * buffer ) +{ +char holdchar; +char nextchar; + + if (tolower(*buffer) != 'e'){ + do { + buffer++; + } + while (ISADIGIT(*buffer)); + } + + holdchar = *buffer; + *buffer++ = '.'; + + do { + nextchar = *buffer; + *buffer = holdchar; + holdchar = nextchar; + } + + while(*buffer++); +} + + +/*** +*_cropzeros(buffer) - removes trailing zeros from floating-point output +*Purpose: +* removes trailing zeros (after the '.') from floating-point output; +* called only when we're doing %g format, there's no '#' flag, and +* precision is non-zero. plays around with the buffer, looking for +* trailing zeros. when we find them, then we move everbody else forward +* so they overlay the zeros. if we eliminate the entire fraction part, +* then we overlay the decimal point ('.'), too. +* +* side effects: changes the buffer from +* [-] digit [digit...] [ . [digits...] [0...] ] [(exponent part)] +* to +* [-] digit [digit...] [ . digit [digits...] ] [(exponent part)] +* or +* [-] digit [digit...] [(exponent part)] +* +*Entry: +* buffer = (char *) pointer to buffer to modify +* +*Exit: +* returns : (void) +* +*Exceptions: +*******************************************************************************/ + +void _cropzeros( char * buf ) +{ +char *stop; + + while (*buf && *buf != '.') + buf++; + + if (*buf++) { + while (*buf && *buf != 'e' && *buf != 'E') + buf++; + + stop = buf--; + + while (*buf == '0') + buf--; + + if (*buf == '.') + buf--; + + while( (*++buf = *stop++) != '\0' ); + } +} + + +int _positive( double * arg ) +{ + return( (*arg >= 0.0) ); +} + + +void _fassign( int flag, char * argument, char * number ) +{ + +/* flag should normally be 2 for long double and 1 for double + * The 32bit input.c sets 3 for long double and 2 for double + * Until this is fixed, decrement flag before use + */ + + --flag; + +#ifdef LONG_DOUBLE + + switch( flag ){ + case 2: + _atoldbl( (_ULDOUBLE *)argument, number ); + break; + + case 1: + _atodbl( (UDOUBLE *)argument, number ); + break; + + default: + _atoflt( (FLOAT *)argument, number ); + } + +#else /* not LONG_DOUBLE */ + if (flag) + _atodbl( (UDOUBLE *)argument, number ); + else + _atoflt( (FLOAT *)argument, number ); +#endif /* not LONG_DOUBLE */ +} + + +#ifndef MTHREAD + static char g_fmt = 0; + static int g_magnitude = 0; + static char g_round_expansion = 0; + static STRFLT g_pflt; +#endif + + +/* + * Function name: _cftoe + * + * Arguments: pvalue - double * pointer + * buf - char * pointer + * ndec - int + * caps - int + * + * Description: _cftoe converts the double pointed to by pvalue to a null + * terminated string of ASCII digits in the c language + * printf %e format, nad returns a pointer to the result. + * This format has the form [-]d.ddde(+/-)ddd, where there + * will be ndec digits following the decimal point. If + * ndec <= 0, no decimal point will appear. The low order + * digit is rounded. If caps is nonzero then the exponent + * will appear as E(+/-)ddd. + * + * Side Effects: the buffer 'buf' is assumed to have a minimum length + * of CVTBUFSIZE (defined in cvt.h) and the routines will + * not write over this size. + * + * Copyright: written R.K. Wyss, Microsoft, Sept. 9, 1983 + * copyright (c) Microsoft Corp. 1983 + * + * History: + * + */ + +#ifdef MTHREAD + static char * _cftoe2( char * buf, int ndec, int caps, STRFLT pflt, char g_fmt ) +#else + char * _cftoe( double * pvalue, char * buf, int ndec, int caps ) +#endif +{ +#ifndef MTHREAD + STRFLT pflt; +#endif + +char *p; +int exp; + +#ifdef MTHREAD + int g_magnitude = pflt->decpt - 1; +#endif + + /* first convert the value */ + + /* place the output in the buffer and round. Leave space in the buffer + * for the '-' sign (if any) and the decimal point (if any) + */ + + if (g_fmt) { +#ifndef MTHREAD + pflt = g_pflt; +#endif + /* shift it right one place if nec. for '.' */ + + p = buf + (pflt->sign == '-'); + _shift(p, (ndec > 0)); + } +#ifndef MTHREAD + else { + + +#ifdef MIPS + + UDOUBLE dtemp; + dtemp = *pvalue; + + pflt = _fltout(dtemp); + + +#else + + UDOUBLE dtemp; + dtemp.x = *pvalue; //i386 case + + pflt = _fltout(dtemp); + + + +#endif + + _fptostr(buf + (pflt->sign == '-') + (ndec > 0), ndec + 1, pflt); + } +#endif + + + /* now fix the number up to be in e format */ + + p = buf; + + /* put in negative sign if needed */ + + if (pflt->sign == '-') + *p++ = '-'; + + /* put in decimal point if needed. Copy the first digit to the place + * left for it and put the decimal point in its place + */ + + if (ndec > 0) { + *p = *(p+1); + *(++p) = '.'; + } + + /* find the end of the string and attach the exponent field */ + + p = strcpy(p+ndec+(!g_fmt), "e+000"); + + /* adjust exponent indicator according to caps flag and increment + * pointer to point to exponent sign + */ + + if (caps) + *p = 'E'; + + p++; + + /* if mantissa is zero, then the number is 0 and we are done; otherwise + * adjust the exponent sign (if necessary) and value. + */ + + if (*pflt->mantissa != '0') { + + /* check to see if exponent is negative; if so adjust exponent sign and + * exponent value. + */ + + if( (exp = pflt->decpt - 1) < 0 ) { + exp = -exp; + *p = '-'; + } + + p++; + + if (exp >= 100) { + *p += (char)(exp / 100); + exp %= 100; + } + p++; + + if (exp >= 10) { + *p += (char)(exp / 10); + exp %= 10; + } + + *++p += (char)exp; + } + + return(buf); +} + + +#ifdef MTHREAD + +char * _cftoe( double * pvalue, char * buf, int ndec, int caps ) +{ +struct _strflt retstrflt; +char resstr[21]; +STRFLT pflt = &retstrflt; + + _fltout2(*pvalue, (struct _strflt *)&retstrflt, + (char *)resstr); + _fptostr(buf + (pflt->sign == '-') + (ndec > 0), ndec + 1, pflt); + _cftoe2(buf, ndec, caps, pflt, /* g_fmt = */ 0); + + return( buf ); +} + +#else /* not MTHREAD */ + +static char * _cftoe_g( double * pvalue, char * buf, int ndec, int caps ) +{ + char *res; + g_fmt = 1; + res = _cftoe(pvalue, buf, ndec, caps); + g_fmt = 0; + return (res); +} + +#endif /* not MTHREAD */ + + +#ifdef MTHREAD +static char * _cftof2( char * buf, int ndec, STRFLT pflt, char g_fmt ) + +#else +char * _cftof( double * pvalue, char * buf, int ndec ) +#endif + +{ +#ifndef MTHREAD +STRFLT pflt; +#endif + +char *p; +char addzero = 0; + +#ifdef MTHREAD +int g_magnitude = pflt->decpt - 1; +#endif + + + /* first convert the value */ + + /* place the output in the users buffer and round. Save space for + * the minus sign now if it will be needed + */ + + if (g_fmt) { +#ifndef MTHREAD + pflt = g_pflt; +#endif + + p = buf + (pflt->sign == '-'); + if (g_magnitude == ndec) { + char *q = p + g_magnitude; + *q++ = '0'; + *q = '\0'; + /* allows for extra place-holding '0' in the exponent == precision + * case of the g format + */ + } + } +#ifndef MTHREAD + else { + + +#ifdef MIPS + + UDOUBLE dtemp; + dtemp = *pvalue; + + pflt = _fltout(dtemp); + + +#else + + UDOUBLE dtemp; + dtemp.x = *pvalue; //i386 case + + pflt = _fltout(dtemp); + + + +#endif + + _fptostr(buf+(pflt->sign == '-'), ndec + pflt->decpt, pflt); + } +#endif + + + /* now fix up the number to be in the correct f format */ + + p = buf; + + /* put in negative sign, if necessary */ + + if (pflt->sign == '-') + *p++ = '-'; + + /* insert leading 0 for purely fractional values and position ourselves + * at the correct spot for inserting the decimal point + */ + + if (pflt->decpt <= 0) { + _shift(p, 1); + *p++ = '0'; + } + else + p += pflt->decpt; + + /* put in decimal point if required and any zero padding needed */ + + if (ndec > 0) { + _shift(p, 1); + *p++ = '.'; + + /* if the value is less than 1 then we may need to put 0's out in + * front of the first non-zero digit of the mantissa + */ + + if (pflt->decpt < 0) { + if( g_fmt ) + ndec = -pflt->decpt; + else + ndec = (ndec < -pflt->decpt ) ? ndec : -pflt->decpt; + _shift(p, ndec); + memset( p, '0', ndec); + } + } + + return( buf); +} + + +/* + * Function name: _cftof + * + * Arguments: value - double * pointer + * buf - char * pointer + * ndec - int + * + * Description: _cftof converts the double pointed to by pvalue to a null + * terminated string of ASCII digits in the c language + * printf %f format, and returns a pointer to the result. + * This format has the form [-]ddddd.ddddd, where there will + * be ndec digits following the decimal point. If ndec <= 0, + * no decimal point will appear. The low order digit is + * rounded. + * + * Side Effects: the buffer 'buf' is assumed to have a minimum length + * of CVTBUFSIZE (defined in cvt.h) and the routines will + * not write over this size. + * + * Copyright: written R.K. Wyss, Microsoft, Sept. 9, 1983 + * copyright (c) Microsoft Corp. 1983 + * + * History: + * + */ + +#ifdef MTHREAD + +char * _cftof( double * pvalue, char * buf, int ndec ) +{ + struct _strflt retstrflt; + char resstr[21]; + STRFLT pflt = &retstrflt; + _fltout2(*pvalue, (struct _strflt *) &retstrflt, + (char *) resstr); + _fptostr(buf+(pflt->sign == '-'), ndec + pflt->decpt, pflt); + _cftof2(buf, ndec, pflt, /* g_fmt = */ 0); + + return( buf ); +} + +#else /* not MTHREAD */ + + +static char * _cftof_g( double * pvalue, char * buf, int ndec ) +{ + char *res; + g_fmt = 1; + res = _cftof(pvalue, buf, ndec); + g_fmt = 0; + return (res); +} + +#endif /* not MTHREAD */ + +/* + * Function name: _cftog + * + * Arguments: value - double * pointer + * buf - char * pointer + * ndec - int + * + * Description: _cftog converts the double pointed to by pvalue to a null + * terminated string of ASCII digits in the c language + * printf %g format, and returns a pointer to the result. + * The form used depends on the value converted. The printf + * %e form will be used if the magnitude of valude is less + * than -4 or is greater than ndec, otherwise printf %f will + * be used. ndec always specifies the number of digits + * following the decimal point. The low order digit is + * appropriately rounded. + * + * Side Effects: the buffer 'buf' is assumed to have a minimum length + * of CVTBUFSIZE (defined in cvt.h) and the routines will + * not write over this size. + * + * Copyright: written R.K. Wyss, Microsoft, Sept. 9, 1983 + * copyright (c) Microsoft Corp. 1983 + * + * History: + * + */ + +char * _cftog( double * pvalue, char * buf, int ndec, int caps ) +{ +char *p; + +#ifdef MTHREAD +char g_round_expansion = 0; +STRFLT g_pflt; +int g_magnitude; +struct _strflt retstrflt; +char resstr[21]; + + /* first convert the number */ + + g_pflt = &retstrflt; + _fltout2(*pvalue, (struct _strflt *)&retstrflt, + (char *)resstr); + +#else /* not MTHREAD */ + + /* first convert the number */ + + +#ifdef MIPS + + UDOUBLE dtemp; + dtemp = *pvalue; + + g_pflt = _fltout(dtemp); + + +#else + + UDOUBLE dtemp; + dtemp.x = *pvalue; //i386 case + + g_pflt = _fltout(dtemp); + + + +#endif + + +#endif /* not MTHREAD */ + + g_magnitude = g_pflt->decpt - 1; + p = buf + (g_pflt->sign == '-'); + + _fptostr(p, ndec, g_pflt); + g_round_expansion = (char)(g_magnitude < (g_pflt->decpt-1)); + + + /* compute the magnitude of value */ + + g_magnitude = g_pflt->decpt - 1; + + /* convert value to the c language g format */ + + if (g_magnitude < -4 || g_magnitude >= ndec){ /* use e format */ + /* (g_round_expansion ==> + * extra digit will be overwritten by 'e+xxx') + */ + +#ifdef MTHREAD + return(_cftoe2(buf, ndec, caps, g_pflt, /* g_fmt = */ 1)); +#else + return(_cftoe_g(pvalue, buf, ndec, caps)); +#endif + + } + else { /* use f format */ + if (g_round_expansion) { + /* throw away extra final digit from expansion */ + while (*p++); + *(p-2) = '\0'; + } + +#ifdef MTHREAD + return(_cftof2(buf, ndec, g_pflt, /* g_fmt = */ 1)); +#else + return(_cftof_g(pvalue, buf, ndec)); +#endif + + } +} + +/*** +*_cfltcvt(arg, buf, format, precision, caps) - convert floating-point output +*Purpose: +* +*Entry: +* arg = (double *) pointer to double-precision floating-point number +* buf = (char *) pointer to buffer into which to put the converted +* ASCII form of the number +* format = (int) 'e', 'f', or 'g' +* precision = (int) giving number of decimal places for %e and %f formats, +* and giving maximum number of significant digits for +* %g format +* caps = (int) flag indicating whether 'E' in exponent should be capatilized +* (for %E and %G formats only) +* +*Exit: +* returns : (void) +* +*Exceptions: +*******************************************************************************/ +/* + * Function name: _cfltcvt + * + * Arguments: arg - double * pointer + * buf - char * pointer + * format - int + * ndec - int + * caps - int + * + * Description: _cfltcvt determines from the format, what routines to + * call to generate the correct floating point format + * + * Side Effects: none + * + * Author: Dave Weil, Jan 12, 1985 + * + * Copyright: Copyright (C) Microsoft Corp. 1985 + */ + +void _cfltcvt( double * arg, char * buffer, int format, int precision, int caps ) +{ + if (format == 'e' || format == 'E') + _cftoe(arg, buffer, precision, caps); + else if (format == 'f') + _cftof(arg, buffer, precision); + else + _cftog(arg, buffer, precision, caps); +} + +/*** +*_shift(s, dist) - shift a null-terminated string in memory (internal routine) +*Purpose: +* _shift is a helper routine that shifts a null-terminated string +* in memory, e.g., moves part of a buffer used for floating-point output +* +* modifies memory locations (s+dist) through (s+dist+strlen(s)) +* +*Entry: +* s = (char *) pointer to string to move +* dist = (int) distance to move the string to the right (if negative, to left) +* +*Exit: +* returns : (void) +* +*Exceptions: +*******************************************************************************/ + +static void _shift( char *s, int dist ) +{ + if( dist ) + memmove(s+dist, s, strlen(s)+1); +} + diff --git a/private/windbg/lib/heap.c b/private/windbg/lib/heap.c new file mode 100644 index 000000000..60c22834a --- /dev/null +++ b/private/windbg/lib/heap.c @@ -0,0 +1,106 @@ +/*++ + + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + heap.c + +Abstract: + + This file contains a heap validation routines. + +Author: + + Wesley Witt (wesw) 2-Feb-94 + +Environment: + + Win32, User Mode + +--*/ + +#include <windows.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <heap.h> + + +// +// used to globally enable or disable heap checking +// +DWORD fHeapCheck = TRUE; + + + +VOID +ValidateTheHeap( + LPSTR fName, + DWORD dwLine + ) +/*++ + +Routine Description: + + Validate the process's heap. If the heap is found to be + invalid then a messagebox is displayed that indicates the + caller's file & line number. If the BO button is pressed + on the message box then DebugBreak is called. + +Arguments: + + fName - caller's source filename + dwLine - caller's source line number + +Return Value: + + None. + +--*/ +{ + CHAR buf[256]; + INT id; + + // + // we don't really want to allocate memory here, since the + // whole point was to look for heap corruption. Instead, + // just preallocate an unreasonable number of slots... + // + + PVOID ProcessHeaps[64]; + DWORD NumberOfHeaps = 64; + DWORD Heap; + + + if (fHeapCheck) { + + NumberOfHeaps = GetProcessHeaps(NumberOfHeaps, ProcessHeaps); + + for (Heap = 0; Heap < NumberOfHeaps; Heap++) { + + if (!HeapValidate( ProcessHeaps[Heap], 0, 0 )) { + + _snprintf( buf, sizeof(buf), + "Heap corruption detected in heap 0x%08x at line %d in %s.\n", + ProcessHeaps[Heap], fName, dwLine ); + + id = MessageBox( NULL, buf, "WinDbg Error", + MB_YESNO | MB_ICONHAND | + MB_TASKMODAL | MB_SETFOREGROUND ); + + OutputDebugString( buf ); + OutputDebugString("\n\r"); + + if (id != IDYES) { + DebugBreak(); + } + + } + + } + + } +} diff --git a/private/windbg/lib/intrncvt.c b/private/windbg/lib/intrncvt.c new file mode 100644 index 000000000..9ce055ffb --- /dev/null +++ b/private/windbg/lib/intrncvt.c @@ -0,0 +1,703 @@ +/*** +* intrncvt.c - internal floating point conversions +* +* Copyright (c) 1992-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* All fp string conversion routines use the same core conversion code +* that converts strings into an internal long double representation +* with an 80-bit mantissa field. The mantissa is represented +* as an array (man) of 32-bit unsigned longs, with man[0] holding +* the high order 32 bits of the mantissa. The binary point is assumed +* to be between the MSB and MSB-1 of man[0]. +* +* Bits are counted as follows: +* +* +* +-- binary point +* | +* v MSB LSB +* ---------------- ------------------ -------------------- +* |0 1 .... 31| | 32 33 ... 63| | 64 65 ... 95| +* ---------------- ------------------ -------------------- +* +* man[0] man[1] man[2] +* +* This file provides the final conversion routines from this internal +* form to the single, double, or long double precision floating point +* format. +* +* All these functions do not handle NaNs (it is not necessary) +* +* +*Revision History: +* 04-29-92 GDP written +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + + +#include <assert.h> +#include "cv.h" + + + + +#define INTRNMAN_LEN 3 /* internal mantissa length in int's */ + +// +// internal mantissaa representation +// for string conversion routines +// + +typedef u_long *intrnman; + + +typedef struct { + int max_exp; // maximum base 2 exponent (reserved for special values) + int min_exp; // minimum base 2 exponent (reserved for denormals) + int precision; // bits of precision carried in the mantissa + int exp_width; // number of bits for exponent + int format_width; // format width in bits + int bias; // exponent bias +} FpFormatDescriptor; + + + +static FpFormatDescriptor +DoubleFormat = { + 0x7ff - 0x3ff, // 1024, maximum base 2 exponent (reserved for special values) + 0x0 - 0x3ff, // -1023, minimum base 2 exponent (reserved for denormals) + 53, // bits of precision carried in the mantissa + 11, // number of bits for exponent + 64, // format width in bits + 0x3ff, // exponent bias +}; + +static FpFormatDescriptor +FloatFormat = { + 0xff - 0x7f, // 128, maximum base 2 exponent (reserved for special values) + 0x0 - 0x7f, // -127, minimum base 2 exponent (reserved for denormals) + 24, // bits of precision carried in the mantissa + 8, // number of bits for exponent + 32, // format width in bits + 0x7f, // exponent bias +}; + + + +// +// function prototypes +// + +int _RoundMan (intrnman man, int nbit); +int _ZeroTail (intrnman man, int nbit); +int _IncMan (intrnman man, int nbit); +void _CopyMan (intrnman dest, intrnman src); +void _CopyMan (intrnman dest, intrnman src); +void _FillZeroMan(intrnman man); +void _Shrman (intrnman man, int n); + +INTRNCVT_STATUS _ld12cvt(_ULDBL12 *pld12, void *d, FpFormatDescriptor *format); + +/*** +* _ZeroTail - check if a mantissa ends in 0's +* +*Purpose: +* Return TRUE if all mantissa bits after nbit (including nbit) are 0, +* otherwise return FALSE +* +* +*Entry: +* man: mantissa +* nbit: order of bit where the tail begins +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +int _ZeroTail (intrnman man, int nbit) +{ + int nl = nbit / 32; + int nb = 31 - nbit % 32; + + + // + // |<---- tail to be checked ---> + // + // -- ------------------------ ---- + // |... | | ... | + // -- ------------------------ ---- + // ^ ^ ^ + // | | |<----nb-----> + // man nl nbit + // + + + + u_long bitmask = ~(MAX_ULONG << nb); + + if (man[nl] & bitmask) + return 0; + + nl++; + + for (;nl < INTRNMAN_LEN; nl++) + if (man[nl]) + return 0; + + return 1; +} + + + + +/*** +* _IncMan - increment mantissa +* +*Purpose: +* +* +*Entry: +* man: mantissa in internal long form +* nbit: order of bit that specifies the end of the part to be incremented +* +*Exit: +* returns 1 on overflow, 0 otherwise +* +*Exceptions: +* +*******************************************************************************/ + +int _IncMan (intrnman man, int nbit) +{ + int nl = nbit / 32; + int nb = 31 - nbit % 32; + + // + // |<--- part to be incremented -->| + // + // -- --------------------------- ---- + // |... | | ... | + // -- --------------------------- ---- + // ^ ^ ^ + // | | |<--nb--> + // man nl nbit + // + + u_long one = (u_long) 1 << nb; + int carry; + + carry = __addl(man[nl], one, &man[nl]); + + nl--; + + for (; nl >= 0 && carry; nl--) { + carry = (u_long) __addl(man[nl], (u_long) 1, &man[nl]); + } + + return carry; +} + + + + +/*** +* _RoundMan - round mantissa +* +*Purpose: +* round mantissa to nbit precision +* +* +*Entry: +* man: mantissa in internal form +* precision: number of bits to be kept after rounding +* +*Exit: +* returns 1 on overflow, 0 otherwise +* +*Exceptions: +* +*******************************************************************************/ + +int _RoundMan (intrnman man, int precision) +{ + int i,rndbit,nl,nb; + u_long rndmask; + int nbit; + int retval = 0; + + // + // The order of the n'th bit is n-1, since the first bit is bit 0 + // therefore decrement precision to get the order of the last bit + // to be kept + // + nbit = precision - 1; + + rndbit = nbit+1; + + nl = rndbit / 32; + nb = 31 - rndbit % 32; + + // + // Get value of round bit + // + + rndmask = (u_long)1 << nb; + + if ((man[nl] & rndmask) && + !_ZeroTail(man, rndbit+1)) { + + // + // round up + // + + retval = _IncMan(man, nbit); + } + + + // + // fill rest of mantissa with zeroes + // + + man[nl] &= MAX_ULONG << nb; + for(i=nl+1; i<INTRNMAN_LEN; i++) { + man[i] = (u_long)0; + } + + return retval; +} + + +/*** +* _CopyMan - copy mantissa +* +*Purpose: +* copy src to dest +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +void _CopyMan (intrnman dest, intrnman src) +{ + u_long *p, *q; + int i; + + p = src; + q = dest; + + for (i=0; i < INTRNMAN_LEN; i++) { + *q++ = *p++; + } +} + + + +/*** +* _FillZeroMan - fill mantissa with zeroes +* +*Purpose: +* +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +void _FillZeroMan(intrnman man) +{ + int i; + for (i=0; i < INTRNMAN_LEN; i++) + man[i] = (u_long)0; +} + + + +/*** +* _IsZeroMan - check if mantissa is zero +* +*Purpose: +* +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +int _IsZeroMan(intrnman man) +{ + int i; + for (i=0; i < INTRNMAN_LEN; i++) + if (man[i]) + return 0; + + return 1; +} + + + + + +/*** +* _ShrMan - shift mantissa to the right +* +*Purpose: +* shift man by n bits to the right +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +void _ShrMan (intrnman man, int n) +{ + int i, n1, n2, mask; + int carry_from_left; + + // + // declare this as volatile in order to work around a C8 + // optimization bug + // + + volatile int carry_to_right; + + n1 = n / 32; + n2 = n % 32; + + mask = ~(MAX_ULONG << n2); + + + // + // first deal with shifts by less than 32 bits + // + + carry_from_left = 0; + for (i=0; i<INTRNMAN_LEN; i++) { + + carry_to_right = man[i] & mask; + + man[i] >>= n2; + + man[i] |= carry_from_left; + + carry_from_left = carry_to_right << (32 - n2); + } + + + // + // now shift whole 32-bit ints + // + + for (i=INTRNMAN_LEN-1; i>=0; i--) { + if (i >= n1) { + man[i] = man[i-n1]; + } + else { + man[i] = 0; + } + } +} + + + + +/*** +* _ld12tocvt - _ULDBL12 floating point conversion +* +*Purpose: +* convert a internal _LBL12 structure into an IEEE floating point +* representation +* +* +*Entry: +* pld12: pointer to the _ULDBL12 +* format: pointer to the format descriptor structure +* +*Exit: +* *d contains the IEEE representation +* returns the INTRNCVT_STATUS +* +*Exceptions: +* +*******************************************************************************/ +INTRNCVT_STATUS _ld12cvt(_ULDBL12 *pld12, void *d, FpFormatDescriptor *format) +{ + u_long man[INTRNMAN_LEN]; + u_long saved_man[INTRNMAN_LEN]; + u_long msw; + unsigned int bexp; // biased exponent + int exp_shift; + int exponent, sign; + INTRNCVT_STATUS retval; + + exponent = (*U_EXP_12(pld12) & 0x7fff) - 0x3fff; // unbias exponent + sign = *U_EXP_12(pld12) & 0x8000; + + // + // bexp is the final biased value of the exponent to be used + // Each of the following blocks should provide appropriate + // values for man, bexp and retval. The mantissa is also + // shifted to the right, leaving space for the exponent + // and sign to be inserted + // + + + if (exponent == 0 - 0x3fff) { + + // either a denormal or zero + bexp = 0; + + if (_IsZeroMan(man)) { + + retval = INTRNCVT_OK; + } + else { + + _FillZeroMan(man); + + // denormal has been flushed to zero + + retval = INTRNCVT_UNDERFLOW; + } + } + else { + + man[0] = *UL_MANHI_12(pld12); + man[1] = *UL_MANLO_12(pld12); + man[2] = *U_XT_12(pld12) << 16; + + // save mantissa in case it needs to be rounded again + // at a different point (e.g., if the result is a denormal) + + _CopyMan(saved_man, man); + + if (_RoundMan(man, format->precision)) { + exponent ++; + } + + if (exponent < format->min_exp - format->precision ) { + + // + // underflow that produces a zero + // + + _FillZeroMan(man); + bexp = 0; + retval = INTRNCVT_UNDERFLOW; + } + + else if (exponent <= format->min_exp) { + + // + // underflow that produces a denormal + // + // + + // The (unbiased) exponent will be MIN_EXP + // Find out how much the mantissa should be shifted + // One shift is done implicitly by moving the + // binary point one bit to the left, i.e., + // we treat the mantissa as .ddddd instead of d.dddd + // (where d is a binary digit) + + int shift = format->min_exp - exponent; + + // The mantissa should be rounded again, so it + // has to be restored + + _CopyMan(man,saved_man); + + _ShrMan(man, shift); + _RoundMan(man, format->precision); // need not check for carry + + // make room for the exponent + sign + + _ShrMan(man, format->exp_width + 1); + + bexp = 0; + retval = INTRNCVT_UNDERFLOW; + + } + + else if (exponent >= format->max_exp) { + + // + // overflow, return infinity + // + + _FillZeroMan(man); + man[0] |= (1 << 31); // set MSB + + // make room for the exponent + sign + + _ShrMan(man, (format->exp_width + 1) - 1); + + bexp = format->max_exp + format->bias; + + retval = INTRNCVT_OVERFLOW; + } + + else { + + // + // valid, normalized result + // + + bexp = exponent + format->bias; + + + // clear implied bit + + man[0] &= (~( 1 << 31)); + + // + // shift right to make room for exponent + sign + // + + _ShrMan(man, (format->exp_width + 1) - 1); + + retval = INTRNCVT_OK; + + } + } + + + exp_shift = 32 - (format->exp_width + 1); + msw = man[0] | + (bexp << exp_shift) | + (sign ? 1<<31 : 0); + + if (format->format_width == 64) { + + *UL_HI_D(d) = msw; + *UL_LO_D(d) = man[1]; + } + + else if (format->format_width == 32) { + + *(u_long *)d = msw; + + } + + return retval; +} + + +/*** +* _ld12tod - convert _ULDBL12 to double +* +*Purpose: +* +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +INTRNCVT_STATUS _ld12tod(_ULDBL12 *pld12, UDOUBLE *d) +{ + return _ld12cvt(pld12, d, &DoubleFormat); +} + + + +/*** +* _ld12tof - convert _ULDBL12 to float +* +*Purpose: +* +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +INTRNCVT_STATUS _ld12tof(_ULDBL12 *pld12, FLOAT *f) +{ + return _ld12cvt(pld12, f, &FloatFormat); +} + + +/*** +* _ld12told - convert _ULDBL12 to 80 bit long double +* +*Purpose: +* +* +*Entry: +* +*Exit: +* +*Exceptions: +* +*******************************************************************************/ +void _ld12told(_ULDBL12 *pld12, _ULDOUBLE *pld) +{ + + // + // This implementation is based on the fact that the _ULDBL12 format is + // identical to the long double and has 2 extra bytes of mantissa + // + + u_short exp, sign; + u_long man[INTRNMAN_LEN]; + + exp = *U_EXP_12(pld12) & (u_short)0x7fff; + sign = *U_EXP_12(pld12) & (u_short)0x8000; + + man[0] = *UL_MANHI_12(pld12); + man[1] = *UL_MANLO_12(pld12); + man[2] = *U_XT_12(pld12) << 16; + + if (_RoundMan(man, 64)) + exp ++; + + *UL_MANHI_LD(pld) = man[0]; + *UL_MANLO_LD(pld) = man[1]; + *U_EXP_LD(pld) = sign | exp; +} + + +void _atodbl(UDOUBLE *d, char *str) +{ + char *EndPtr; + _ULDBL12 ld12; + + __strgtold12(&ld12, &EndPtr, str, 0 ); + _ld12tod(&ld12, d); +} + + +void _atoldbl(_ULDOUBLE *ld, char *str) +{ + char *EndPtr; + _ULDBL12 ld12; + + __strgtold12(&ld12, &EndPtr, str, 0 ); + _ld12told(&ld12, ld); +} + + +void _atoflt(FLOAT *f, char *str) +{ + char *EndPtr; + _ULDBL12 ld12; + + __strgtold12(&ld12, &EndPtr, str, 0 ); + _ld12tof(&ld12, f); +} diff --git a/private/windbg/lib/makefile b/private/windbg/lib/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/windbg/lib/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/windbg/lib/mantold.c b/private/windbg/lib/mantold.c new file mode 100644 index 000000000..05dc6db7c --- /dev/null +++ b/private/windbg/lib/mantold.c @@ -0,0 +1,184 @@ +/*** +*mantold.c - conversion of a decimal mantissa to _ULDBL12 +* +* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Conversion of a decimal mantissa into _ULDBL12 format (i.e. long +* double with two additional bytes of significand) +* +*Revision History: +* 7-17-91 GDP Initial version (ported from assembly) +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + +#include "cv.h" + + + + + + +/*** +*int __addl(u_long x, u_long y, u_long *sum) - u_long addition +* +*Purpose: add two u_long numbers and return carry +* +*Entry: u_long x, u_long y : the numbers to be added +* u_long *sum : where to store the result +* +*Exit: *sum receives the value of x+y +* the value of the carry is returned +* +*Exceptions: +* +*******************************************************************************/ + +int __addl(u_long x, u_long y, u_long *sum) +{ + u_long r; + int carry=0; + r = x+y; + if (r < x || r < y) + carry++; + *sum = r; + return carry; +} + + + + + + +/*** +*void __add_12(_ULDBL12 *x, _ULDBL12 *y) - _ULDBL12 addition +* +*Purpose: add two _ULDBL12 numbers. The numbers are added +* as 12-byte integers. Overflow is ignored. +* +*Entry: x,y: pointers to the operands +* +*Exit: *x receives the sum +* +*Exceptions: +* +*******************************************************************************/ + +void __add_12(_ULDBL12 *x, _ULDBL12 *y) +{ + int c0,c1,c2; + c0 = __addl(*UL_LO_12(x),*UL_LO_12(y),UL_LO_12(x)); + if (c0) { + c1 = __addl(*UL_MED_12(x),(u_long)1,UL_MED_12(x)); + if (c1) { + (*UL_HI_12(x))++; + } + } + c2 = __addl(*UL_MED_12(x),*UL_MED_12(y),UL_MED_12(x)); + if (c2) { + (*UL_HI_12(x))++; + } + /* ignore next carry -- assume no overflow will occur */ + (void) __addl(*UL_HI_12(x),*UL_HI_12(y),UL_HI_12(x)); +} + + + + + +/*** +*void __shl_12(_ULDBL12 *x) - _ULDBL12 shift left +*void __shr_12(_ULDBL12 *x) - _ULDBL12 shift right +* +*Purpose: Shift a _ULDBL12 number one bit to the left (right). The number +* is shifted as a 12-byte integer. The MSB is lost. +* +*Entry: x: a pointer to the operand +* +*Exit: *x is shifted one bit to the left (or right) +* +*Exceptions: +* +*******************************************************************************/ + +void __shl_12(_ULDBL12 *p) +{ + u_long c0,c1; + + c0 = *UL_LO_12(p) & MSB_ULONG ? 1: 0; + c1 = *UL_MED_12(p) & MSB_ULONG ? 1: 0; + *UL_LO_12(p) <<= 1; + *UL_MED_12(p) = *UL_MED_12(p)<<1 | c0; + *UL_HI_12(p) = *UL_HI_12(p)<<1 | c1; +} + +void __shr_12(_ULDBL12 *p) +{ + u_long c2,c1; + c2 = *UL_HI_12(p) & 0x1 ? MSB_ULONG: 0; + c1 = *UL_MED_12(p) & 0x1 ? MSB_ULONG: 0; + *UL_HI_12(p) >>= 1; + *UL_MED_12(p) = *UL_MED_12(p)>>1 | c2; + *UL_LO_12(p) = *UL_LO_12(p)>>1 | c1; +} + + + + + + +/*** +*void __mtold12(char *manptr,unsigned manlen,_ULDBL12 *ld12) - +* convert a mantissa into a _ULDBL12 +* +*Purpose: convert a mantissa into a _ULDBL12. The mantissa is +* in the form of an array of manlen BCD digits and is +* considered to be an integer. +* +*Entry: manptr: the array containing the packed BCD digits of the mantissa +* manlen: the size of the array +* ld12: a pointer to the long double where the result will be stored +* +*Exit: +* ld12 gets the result of the conversion +* +*Exceptions: +* +*******************************************************************************/ + +void __mtold12(char *manptr, + unsigned manlen, + _ULDBL12 *ld12) +{ + _ULDBL12 tmp; + u_short expn = LD_BIASM1+80; + + *UL_LO_12(ld12) = 0; + *UL_MED_12(ld12) = 0; + *UL_HI_12(ld12) = 0; + for (;manlen>0;manlen--,manptr++){ + tmp = *ld12; + __shl_12(ld12); + __shl_12(ld12); + __add_12(ld12,&tmp); + __shl_12(ld12); /* multiply by 10 */ + *UL_LO_12(&tmp) = (u_long)*manptr; + *UL_MED_12(&tmp) = 0; + *UL_HI_12(&tmp) = 0; + __add_12(ld12,&tmp); + } + + /* normalize mantissa -- first shift word by word */ + while (*UL_HI_12(ld12) == 0) { + *UL_HI_12(ld12) = *UL_MED_12(ld12) >> 16; + *UL_MED_12(ld12) = *UL_MED_12(ld12) << 16 | *UL_LO_12(ld12) >> 16; + (*UL_LO_12(ld12)) <<= 16; + expn -= 16; + } + while ((*UL_HI_12(ld12) & 0x8000) == 0) { + __shl_12(ld12); + expn--; + } + *U_EXP_12(ld12) = expn; +} diff --git a/private/windbg/lib/rtlproto.h b/private/windbg/lib/rtlproto.h new file mode 100644 index 000000000..b0c3e76ca --- /dev/null +++ b/private/windbg/lib/rtlproto.h @@ -0,0 +1,88 @@ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntdbg.h> + +// +// Convert between signed and unsigned +// + +// LARGE_INTEGER +// _CRTAPI1 +// RtlConvertULargeIntegerToSigned(ULARGE_INTEGER uli); +#define RtlConvertULargeIntegerToSigned(uli) (*(PLARGE_INTEGER)(&(uli))) + + +// ULARGE_INTEGER +// _CRTAPI1 +// RtlConvertLargeIntegerToUnsigned(LARGE_INTEGER li); +#define RtlConvertLargeIntegerToUnsigned(li) (*((PULARGE_INTEGER)(&(li)))) + + +// +// math routines for ULARGE_INTEGERs +// + +ULARGE_INTEGER +// _CRTAPI1 +RtlULargeIntegerNegate(ULARGE_INTEGER); + + +/* + * #define RtlULargeIntegerNegate(uli) RtlConvertLargeIntegerToUnsigned( \ + * RtlLargeIntegerNegate( \ + * RtlConvertULargeIntegerToSigned(uli))) +**/ + +BOOLEAN +// _CRTAPI1 +RtlULargeIntegerEqualToZero(ULARGE_INTEGER); +/* #define RtlULargeIntegerEqualToZero(uli) RtlConvertLargeIntegerToUnsigned( \ + * RtlLargeIntegerEqualToZero( \ + * RtlConvertULargeIntegerToSigned(uli))) +**/ + + +// +// from strtoli.c +// + +LARGE_INTEGER +// _CRTAPI1 +strtoli ( const char *, char **, int ); + +ULARGE_INTEGER +// _CRTAPI1 +strtouli ( const char *, char **, int ); + + + +// +// Large integer and - 64-bite & 64-bits -> 64-bits. +// + +#define RtlLargeIntegerOr(Result, Source, Mask) \ + { \ + Result.HighPart = Source.HighPart | Mask.HighPart; \ + Result.LowPart = Source.LowPart | Mask.LowPart; \ + } + + + + +// +// Arithmetic right shift (the one in ntrtl.h is logical) +// + +LARGE_INTEGER +// _CRTAPI1 +RtlLargeIntegerArithmeticShiftRight(LARGE_INTEGER, CCHAR); + + +// +// bit-wise negation +// +#define RtlLargeIntegerBitwiseNot(li) \ + li.LowPart = ~li.LowPart; \ + li.HighPart = ~li.HighPart; diff --git a/private/windbg/lib/sources b/private/windbg/lib/sources new file mode 100644 index 000000000..609a6a8f4 --- /dev/null +++ b/private/windbg/lib/sources @@ -0,0 +1,48 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Miche Baker-Harvey (v-michbh) + +!ENDIF + +MAJORCOMP=windbg +MINORCOMP=mathlib + +TARGETNAME=mathlib +TARGETPATH=obj +TARGETTYPE=LIBRARY + +SOURCES=strtoli.c \ + strgtold.c \ + mantold.c \ + tenpow.c \ + constpow.c \ + x10fout.c \ + cvt.c \ + cfout.c \ + cfin.c \ + intrncvt.c \ + atold.c \ + heap.c + + +UMTYPE=windows + +INCLUDES=..\osdebug\include + +!include ..\common.src diff --git a/private/windbg/lib/strgtold.c b/private/windbg/lib/strgtold.c new file mode 100644 index 000000000..5f2d374d0 --- /dev/null +++ b/private/windbg/lib/strgtold.c @@ -0,0 +1,393 @@ +/*** +*strgtold.c - conversion of a string into a long double +* +* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: convert a fp constant into a 10 byte long double (IEEE format) +* +*Revision History: +* 7-17-91 GDP Initial version (ported from assembly) +* 4-03-92 GDP Preserve sign of -0 +* 4-30-92 GDP Now returns _ULDBL12 instead of _ULDOUBLE +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + +//#include <ctype.h> /* for 'isdigit' macro */ +#include "cv.h" + + + +/* local macros */ +#define ISNZDIGIT(x) ((x)>='1' && (x)<='9' ) + +//NOTENOTE the following takes the place of the isdigit() macro +// which does not work for a yet to be determined reason +#define ISADIGIT(x) ((x)>='0' && (x)<='9' ) + +#define ISWHITE(x) ((x)==' ' || (x)=='\t' || (x)=='\n' || (x)=='\r' ) + + + + +/**** +*unsigned int __strgtold( _ULDBL12 *pld12, +* char * * pEndPtr, +* char * str, +* int Mult12 ) +* +*Purpose: +* converts a character string into a long double +* +*Entry: +* pld12 - pointer to the _ULDBL12 where the result should go. +* pEndStr - pointer to a far pointer that will be set to the end of string. +* str - pointer to the string to be converted. +* Mult12 - set to non zero if the _ULDBL12 multiply should be used instead of +* the long double mulitiply. +* +*Exit: +* Returns the SLD_* flags or'ed together. +* +*Uses: +* +*Exceptions: +* +********************************************************************************/ + +unsigned int +__strgtold12(_ULDBL12 *pld12, + char * *p_end_ptr, + char *str, + int mult12) +{ + typedef enum { + S_INIT, /* initial state */ + S_EAT0L, /* eat 0's at the left of mantissa */ + S_SIGNM, /* just read sign of mantissa */ + S_GETL, /* get integer part of mantissa */ + S_GETR, /* get decimal part of mantissa */ + S_POINT, /* just found decimal point */ + S_E, /* just found 'E', or 'e', etc */ + S_SIGNE, /* just read sign of exponent */ + S_EAT0E, /* eat 0's at the left of exponent */ + S_GETE, /* get exponent */ + S_END /* final state */ + } state_t; + + /* this will accomodate the digits of the mantissa in BCD form*/ + static char buf[LD_MAX_MAN_LEN1]; + char *manp = buf; + + /* a temporary _ULDBL12 */ + _ULDBL12 tmpld12; + + u_short man_sign = 0; /* to be ORed with result */ + int exp_sign = 1; /* default sign of exponent (values: +1 or -1)*/ + /* number of decimal significant mantissa digits so far*/ + unsigned manlen = 0; + int found_digit = 0; + int overflow = 0; + int underflow = 0; + int pow = 0; + int exp_adj = 0; /* exponent adjustment */ + u_long ul0,ul1; + u_short u,uexp; + + unsigned int result_flags = 0; + + state_t state = S_INIT; + + char c; /* the current input symbol */ + char *p; /* a pointer to the next input symbol */ + char *savedp; + + for(savedp=p=str;ISWHITE(*p);p++); /* eat up white space */ + + while (state != S_END) { + c = *p++; + switch (state) { + case S_INIT: + if (ISNZDIGIT(c)) { + state = S_GETL; + p--; + } + else + switch (c) { + case '0': + state = S_EAT0L; + break; + case '+': + state = S_SIGNM; + man_sign = 0x0000; + break; + case '-': + state = S_SIGNM; + man_sign = 0x8000; + break; + case '.': + state = S_POINT; + break; + default: + state = S_END; + p--; + break; + } + break; + case S_EAT0L: + found_digit = 1; + if (ISNZDIGIT(c)) { + state = S_GETL; + p--; + } + else + switch (c) { + case '0': + state = S_EAT0L; + break; + case 'E': + case 'e': + case 'D': + case 'd': + state = S_E; + break; + case '.': + state = S_GETR; + break; + default: + state = S_END; + p--; + } + break; + case S_SIGNM: + if (ISNZDIGIT(c)) { + state = S_GETL; + p--; + } + else + switch (c) { + case '0': + state = S_EAT0L; + break; + case '.': + state = S_POINT; + break; + default: + state = S_END; + p = savedp; + } + break; + case S_GETL: + found_digit = 1; + for (;ISADIGIT(c);c=*p++) { + if (manlen < LD_MAX_MAN_LEN+1){ + manlen++; + *manp++ = c - (char)'0'; + } + else + exp_adj++; + } + switch (c) { + case '.': + state = S_GETR; + break; + case 'E': + case 'e': + case 'D': + case 'd': + state = S_E; + break; + default: + state = S_END; + p--; + } + break; + case S_GETR: + found_digit = 1; + if (manlen == 0) + for (;c=='0';c=*p++) + exp_adj--; + for(;ISADIGIT(c);c=*p++){ + if (manlen < LD_MAX_MAN_LEN+1){ + manlen++; + *manp++ = c - (char)'0'; + exp_adj--; + } + } + switch (c){ + case 'E': + case 'e': + case 'D': + case 'd': + state = S_E; + break; + default: + state = S_END; + p--; + } + break; + case S_POINT: + if (ISADIGIT(c)){ + state = S_GETR; + p--; + } + else{ + state = S_END; + p = savedp; + } + break; + case S_E: + savedp = p-2; /* savedp points to 'E' */ + if (ISNZDIGIT(c)){ + state = S_GETE; + p--; + } + else + switch (c){ + case '0': + state = S_EAT0E; + break; + case '-': + state = S_SIGNE; + exp_sign = -1; + break; + case '+': + state = S_SIGNE; + break; + default: + state = S_END; + p = savedp; + } + break; + case S_EAT0E: + for(;c=='0';c=*p++); + if (ISNZDIGIT(c)){ + state = S_GETE; + p--; + } + else { + state = S_END; + p--; + } + break; + case S_SIGNE: + if (ISNZDIGIT(c)){ + state = S_GETE; + p--; + } + else + switch (c){ + case '0': + state = S_EAT0E; + break; + default: + state = S_END; + p = savedp; + } + break; + case S_GETE: + { + long longpow=0; /* TMAX10*10 should fit in a long */ + for(;ISADIGIT(c);c=*p++){ + longpow = longpow*10 + (c - '0'); + if (longpow > TMAX10){ + longpow = TMAX10+1; /* will force overflow */ + break; + } + } + pow = (int)longpow; + } + for(;ISADIGIT(c);c=*p++); /* eat up remaining digits */ + state = S_END; + p--; + break; + } /* switch */ + } /* while */ + + *p_end_ptr = p; /* set end pointer */ + + /* + * Compute result + */ + + if (found_digit && !overflow && !underflow) { + if (manlen>LD_MAX_MAN_LEN){ + if (buf[LD_MAX_MAN_LEN-1]>=5) { + /* + * Round mantissa to MAX_MAN_LEN digits + * It's ok to round 9 to 0ah + */ + buf[LD_MAX_MAN_LEN-1]++; + } + manlen = LD_MAX_MAN_LEN; + manp--; + exp_adj++; + } + if (manlen>0) { + /* + * Remove trailing zero's from mantissa + */ + for(manp--;*manp==0;manp--) { + /* there is at least one non-zero digit */ + manlen--; + exp_adj++; + } + __mtold12(buf,manlen,&tmpld12); + + if (exp_sign < 0) + pow = -pow; + pow += exp_adj; + if (pow > TMAX10) + overflow = 1; + else if (pow < TMIN10) + underflow = 1; + else { + __multtenpow12(&tmpld12,pow,mult12); + + u = *U_XT_12(&tmpld12); + ul0 =*UL_MANLO_12(&tmpld12); + ul1 = *UL_MANHI_12(&tmpld12); + uexp = *U_EXP_12(&tmpld12); + + } + } + else { + /* manlen == 0, so return 0 */ + u = (u_short)0; + ul0 = ul1 = uexp = 0; + } + } + + if (!found_digit) { + /* return 0 */ + u = (u_short)0; + ul0 = ul1 = uexp = 0; + result_flags |= SLD_NODIGITS; + } + else if (overflow) { + /* return +inf or -inf */ + uexp = (u_short)0x7fff; + ul1 = 0x80000000; + ul0 = 0; + u = (u_short)0; + result_flags |= SLD_OVERFLOW; + } + else if (underflow) { + /* return 0 */ + u = (u_short)0; + ul0 = ul1 = uexp = 0; + result_flags |= SLD_UNDERFLOW; + } + + /* + * Assemble result + */ + + *U_XT_12(pld12) = u; + *UL_MANLO_12(pld12) = ul0; + *UL_MANHI_12(pld12) = ul1; + *U_EXP_12(pld12) = uexp | man_sign; + + return result_flags; +} + diff --git a/private/windbg/lib/strtoli.c b/private/windbg/lib/strtoli.c new file mode 100644 index 000000000..9d834c39f --- /dev/null +++ b/private/windbg/lib/strtoli.c @@ -0,0 +1,242 @@ +/*** +*strtoli.c - Contains C runtimes strtol and strtoul +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* Copyright (c) 1989-1993, Digital Equipment Corporation. All rights reserved. +* +*Purpose: +* strtoli - convert ascii string to long signed large integer +* strtouli - convert ascii string to long unsigned large integer +* +*Revision History: +* 04-28-93 MBH Module created, based on strtol.c +* +*******************************************************************************/ + + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntdbg.h> + + +#include <windows.h> +#include <shellapi.h> + + + + +// #include <cruntime.h> +#include <stdlib.h> +#include <limits.h> +#include <errno.h> +#include <ctype.h> + + +/*** +*strtoli, strtouli(nptr,endptr,ibase) - Convert ascii string to long un/signed +* large integer. +* +*Purpose: +* Convert an ascii string to a long 64-bit value. The base +* used for the caculations is supplied by the caller. The base +* must be in the range 0, 2-36. If a base of 0 is supplied, the +* ascii string must be examined to determine the base of the +* number: +* (a) First char = '0', second char = 'x' or 'X', +* use base 16. +* (b) First char = '0', use base 8 +* (c) First char in range '1' - '9', use base 10. +* +* If the 'endptr' value is non-NULL, then strtoli/strtouli places +* a pointer to the terminating character in this value. +* See ANSI standard for details +* +*Entry: +* nptr == NEAR/FAR pointer to the start of string. +* endptr == NEAR/FAR pointer to the end of the string. +* ibase == integer base to use for the calculations. +* +* string format: [whitespace] [sign] [0] [x] [digits/letters] +* +*Exit: +* Good return: +* result +* +* Overflow return: +* strtoli -- LONG_MAX or LONG_MIN in HighPart +* strtouli -- ULONG_MAX in HighPart +* strtoli/strtouli -- errno == ERANGE +* +* No digits or bad base return: +* 0 +* endptr = nptr* +* +*Exceptions: +* None. +*******************************************************************************/ + +/* flag values */ +#define FL_UNSIGNED 1 /* strtoul called */ +#define FL_NEG 2 /* negative sign found */ +#define FL_OVERFLOW 4 /* overflow occured */ +#define FL_READDIGIT 8 /* we've read at least one correct digit */ + +static +LARGE_INTEGER +// MBH - if this is a library, this should be CRTAPI3 +_CRTAPI2 strtoxl ( + const char *nptr, + const char **endptr, + int ibase, + int flags + ) +{ + const char *p; + char c; + + LARGE_INTEGER number; // being computed + unsigned long digval; // each digit in turn + LARGE_INTEGER maxval; // value more than which --> overflow + LARGE_INTEGER maxli; // largest possible large integer + unsigned long remainder; // maxli=maxval/radix + remainder + + p = nptr; /* p is our scanning pointer */ + number.QuadPart = 0; + maxli.QuadPart = -1; + + c = *p++; /* read char */ + while ( isspace((int)(unsigned char)c) ) + c = *p++; /* skip whitespace */ + + if (c == '-') { + flags |= FL_NEG; /* remember minus sign */ + c = *p++; + } + else if (c == '+') + c = *p++; /* skip sign */ + + if (ibase < 0 || ibase == 1 || ibase > 36) { + /* bad base! */ + if (endptr) + /* store beginning of string in endptr */ + *endptr = nptr; + number.QuadPart = 0; + return number; + } + else if (ibase == 0) { + /* determine base free-lance, based on first two chars of + string */ + if (c != '0') + ibase = 10; + else if (*p == 'x' || *p == 'X') + ibase = 16; + else + ibase = 8; + } + + if (ibase == 16) { + /* we might have 0x in front of number; remove if there */ + if (c == '0' && (*p == 'x' || *p == 'X')) { + ++p; + c = *p++; /* advance past prefix */ + } + } + + /* if our number exceeds this, we will overflow on multiply */ + maxval.QuadPart = maxli.QuadPart / ibase; + remainder = (unsigned long)(maxli.QuadPart - maxval.QuadPart); + + for (;;) { /* exit in middle of loop */ + /* convert c to value */ + if ( isdigit((int)(unsigned char)c) ) + digval = c - '0'; + else if ( isalpha((int)(unsigned char)c) ) + digval = toupper(c) - 'A' + 10; + else + break; + if (digval >= (unsigned)ibase) + break; /* exit loop if bad digit found */ + + /* record the fact we have read one digit */ + flags |= FL_READDIGIT; + + /* we now need to compute number = number * base + digval, + but we need to know if overflow occured. This requires + a tricky pre-check. */ + + if (number.QuadPart <= maxval.QuadPart && digval <= remainder) { + // + // we won't overflow, go ahead and multiply + // + number.QuadPart = (number.QuadPart * ibase) + digval; + } else { + // + // we would have overflowed -- set the overflow flag + // + flags |= FL_OVERFLOW; + } + + c = *p++; /* read next digit */ + } + + --p; /* point to place that stopped scan */ + + if (!(flags & FL_READDIGIT)) { + /* no number there; return 0 and point to beginning of + string */ + if (endptr) + /* store beginning of string in endptr later on */ + p = nptr; + /* return 0 */ + number.QuadPart = 0; + } + else if ((flags & FL_OVERFLOW) || (!(flags & FL_UNSIGNED) && (number.QuadPart < 0))) { + + /* overflow occurred or signed overflow occurred */ + errno = ERANGE; + if (flags & FL_UNSIGNED) + number.QuadPart = maxli.QuadPart >> 1; + else + /* set error code, will be negated if necc. */ + number = maxli; + } + + if (endptr != NULL) + /* store pointer to char that stopped the scan */ + *endptr = p; + + if (flags & FL_NEG) + /* negate result if there was a neg sign */ + number.QuadPart = number.QuadPart * -1; + + return number; /* done. */ +} + +LARGE_INTEGER +// _CRTAPI1 +strtoli ( + const char *nptr, + char **endptr, + int ibase + ) +{ + return strtoxl(nptr, endptr, ibase, 0); +} + +ULARGE_INTEGER +// _CRTAPI1 +strtouli ( + const char *nptr, + char **endptr, + int ibase + ) +{ + ULARGE_INTEGER uli; + LARGE_INTEGER li; + + li = strtoxl(nptr, endptr, ibase, FL_UNSIGNED); + uli.LowPart = li.LowPart; + uli.HighPart = li.HighPart; + return uli; +} diff --git a/private/windbg/lib/tenpow.c b/private/windbg/lib/tenpow.c new file mode 100644 index 000000000..0c7cad76b --- /dev/null +++ b/private/windbg/lib/tenpow.c @@ -0,0 +1,240 @@ +/*** +*tenpow.c - multiply a _ULDBL12 by a power of 10 +* +* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* +*Revision History: +* 7-17-91 GDP Initial version (ported from assembly) +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + + +#include "cv.h" + + + +extern _ULDBL12 _pow10pos[]; +extern _ULDBL12 _pow10neg[]; + + + + +/*** +*void __ld12mul(_ULDBL12 *px, _ULDBL12 *py) - +* _ULDBL12 multiplication +* +*Purpose: multiply two _ULDBL12 numbers +* +*Entry: px,py: pointers to the _ULDBL12 operands +* +*Exit: *px contains the product +* +*Exceptions: +* +*******************************************************************************/ + +void __ld12mul(_ULDBL12 *px, _ULDBL12 *py) +{ + u_short sign = 0; + u_short sticky_bits = 0; + _ULDBL12 tempman; /*this is actually a 12-byte mantissa, + not a 12-byte long double */ + int i; + u_short expx, expy, expsum; + int roffs,poffs,qoffs; + int sticky; + + *UL_LO_12(&tempman) = 0; + *UL_MED_12(&tempman) = 0; + *UL_HI_12(&tempman) = 0; + + expx = *U_EXP_12(px); + expy = *U_EXP_12(py); + + sign = (expx ^ expy) & (u_short)0x8000; + expx &= 0x7fff; + expy &= 0x7fff; + expsum = expx+expy; + if (expx >= LD_MAXEXP + || expy >= LD_MAXEXP + || expsum > LD_MAXEXP+ LD_BIASM1){ + /* overflow to infinity */ + PUT_INF_12(px,sign); + return; + } + if (expsum <= LD_BIASM1-63) { + /* underflow to zero */ + PUT_ZERO_12(px); + return; + } + if (expx == 0) { + /* + * If this is a denormal temp real then the mantissa + * was shifted right once to set bit 63 to zero. + */ + expsum++; /* Correct for this */ + if (ISZERO_12(px)) { + /* put positive sign */ + *U_EXP_12(px) = 0; + return; + } + } + if (expy == 0) { + expsum++; /* because arg2 is denormal */ + if (ISZERO_12(py)) { + PUT_ZERO_12(px); + return; + } + } + + roffs = 0; + for (i=0;i<5;i++) { + int j; + poffs = i<<1; + qoffs = 8; + for (j=5-i;j>0;j--) { + u_long prod; +#ifdef MIPS + /* a variable to hold temprary sums */ + u_long sum; +#endif + int carry; + u_short *p, *q; + u_long *r; + p = USHORT_12(px,poffs); + q = USHORT_12(py,qoffs); + r = ULONG_12(&tempman,roffs); + prod = (u_long)*p * (u_long)*q; +#ifdef MIPS + /* handle misalignment problems */ + if (i&0x1){ /* i is odd */ + carry = __addl(*MIPSALIGN(r), prod, &sum); + *MIPSALIGN(r) = sum; + } + else /* i is even */ + carry = __addl(*r, prod, r); +#else + carry = __addl(*r,prod,r); +#endif + if (carry) { + /* roffs should be less than 8 in this case */ + (*USHORT_12(&tempman,roffs+4))++; + } + poffs+=2; + qoffs-=2; + } + roffs+=2; + } + + expsum -= LD_BIASM1; + + /* normalize */ + while ((s_short)expsum > 0 && + ((*UL_HI_12(&tempman) & MSB_ULONG) == 0)) { + __shl_12(&tempman); + expsum--; + } + + if ((s_short)expsum <= 0) { + expsum--; + while ((s_short)expsum < 0) { + if (*U_XT_12(&tempman) & 0x1) + sticky++; + __shr_12(&tempman); + expsum++; + } + if (sticky) + *U_XT_12(&tempman) |= 0x1; + } + + if (*U_XT_12(&tempman) > 0x8000 || + ((*UL_LO_12(&tempman) & 0x1ffff) == 0x18000)) { + /* round up */ + if (*UL_MANLO_12(&tempman) == MAX_ULONG) { + *UL_MANLO_12(&tempman) = 0; + if (*UL_MANHI_12(&tempman) == MAX_ULONG) { + *UL_MANHI_12(&tempman) = 0; + if (*U_EXP_12(&tempman) == MAX_USHORT) { + /* 12-byte mantissa overflow */ + *U_EXP_12(&tempman) = MSB_USHORT; + expsum++; + } + else + (*U_EXP_12(&tempman))++; + } + else + (*UL_MANHI_12(&tempman))++; + } + else + (*UL_MANLO_12(&tempman))++; + } + + + /* check for exponent overflow */ + if (expsum >= 0x7fff){ + PUT_INF_12(px, sign); + return; + } + + /* put result in px */ + *U_XT_12(px) = *USHORT_12(&tempman,2); + *UL_MANLO_12(px) = *UL_MED_12(&tempman); + *UL_MANHI_12(px) = *UL_HI_12(&tempman); + *U_EXP_12(px) = expsum | sign; +} + + + +void __multtenpow12(_ULDBL12 *pld12, int pow, unsigned mult12) +{ + _ULDBL12 *pow_10p = _pow10pos-8; + if (pow == 0) + return; + if (pow < 0) { + pow = -pow; + pow_10p = _pow10neg-8; + } + + if (!mult12) + *U_XT_12(pld12) = 0; + + + while (pow) { + int last3; /* the 3 LSBits of pow */ + _ULDBL12 unround; + _ULDBL12 *py; + + pow_10p += 7; + last3 = pow & 0x7; + pow >>= 3; + if (last3 == 0) + continue; + py = pow_10p + last3; + +#ifdef _ULDSUPPORT + if (mult12) { +#endif + /* do an exact 12byte multiplication */ + if (*U_XT_12(py) >= 0x8000) { + /* copy number */ + unround = *py; + /* unround adjacent byte */ + (*UL_MANLO_12(&unround))--; + /* point to new operand */ + py = &unround; + } + __ld12mul(pld12,py); +#ifdef _ULDSUPPORT + } + else { + /* do a 10byte multiplication */ + py = (_ULDBL12 *)TEN_BYTE_PART(py); + *(long double *)TEN_BYTE_PART(pld12) *= + *(long double *)py; + } +#endif + } +} diff --git a/private/windbg/lib/x10fout.c b/private/windbg/lib/x10fout.c new file mode 100644 index 000000000..a71fc9019 --- /dev/null +++ b/private/windbg/lib/x10fout.c @@ -0,0 +1,464 @@ +/*** +*x10fout.c - floating point output for 10-byte long double +* +* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Support conversion of a long double into a string +* +*Revision History: +* 07/15/91 GDP Initial version in C (ported from assembly) +* 01/23/92 GDP Support MIPS encoding for NaN +* 05-26-92 GWK Windbg srcs +* +*******************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include "cv.h" + + + +#define STRCPY strcpy + +#define PUT_ZERO_FOS(fos) \ + fos->exp = 1, \ + fos->sign = ' ', \ + fos->ManLen = 1, \ + fos->man[0] = '0',\ + fos->man[1] = 0; + +#define SNAN_STR "1#SNAN" +#define SNAN_STR_LEN 6 +#define QNAN_STR "1#QNAN" +#define QNAN_STR_LEN 6 +#define INF_STR "1#INF" +#define INF_STR_LEN 5 +#define IND_STR "1#IND" +#define IND_STR_LEN 5 + +#define MAX_10_LEN 30 //max length of string including NULL + +/*** +char * _uldtoa (_ULDOUBLE *px, +* int maxchars, +* char *ldtext) +* +* +*Purpose: +* Return pointer to filled in string "ldtext" for +* a given _UDOUBLE ponter px +* with a maximum character width of maxchars +* +*Entry: +* _ULDOUBLE * px: a pointer to the long double to be converted into a string +* int maxchars: number of digits allowed in the output format. +* +* (default is 'e' format) +* +* char * ldtext: a pointer to the output string +* +*Exit: +* returns pointer to the output string +* +*Exceptions: +* +*******************************************************************************/ + + +char * _uldtoa (_ULDOUBLE *px, int maxchars, char *ldtext) +{ + char in_str [250]; + char in_str2 [250]; + char cExp[20]; + FOS foss; + char * lpszMan; + char * lpIndx; + int nErr; + int len1, len2; + + maxchars -= 8; /* sign, dot, E+0001 */ + + nErr = $I10_OUTPUT (*px, maxchars, 0, &foss); + + lpszMan = foss.man; + + ldtext[0] = foss.sign; + ldtext[1] = *lpszMan; + ldtext[2] = '.'; + ldtext[3] = '\0'; + + maxchars += 2; /* sign, dot */ + + lpszMan++; + strcat (ldtext, lpszMan); + + len1 = strlen (ldtext); // for 'e' + + + strcpy (cExp, "e"); + + foss.exp -= 1; /* Adjust for the shift decimal shift above */ + _itoa (foss.exp, in_str, 10); + + + if (foss.exp < 0) { + strcat (cExp, "-"); + + strcpy (in_str2, &in_str[1]); + strcpy (in_str, in_str2); + + while (strlen(in_str) < 4) { + strcpy (in_str2, in_str); + strcpy (in_str,"0"); + strcat (in_str,in_str2); + } + } else { + while (strlen(in_str) < 4) { + strcpy (in_str2, in_str); + strcpy (in_str,"0"); + strcat (in_str,in_str2); + } + } + + if (foss.exp >= 0) { + strcat (cExp, "+"); + } + + strcat (cExp, in_str); + + len2 = strlen (cExp); + + if (len1 == maxchars) { + ; + } + else if (len1 < maxchars) { + do { + strcat (ldtext,"0"); + len1++; + } while (len1 < maxchars); + } + else { + lpIndx = &ldtext[len1 - 1]; // point to last char and round + do { + *lpIndx = '\0'; + lpIndx--; + len1--; //NOTENOTE v-griffk we really need to round + } while (len1 > maxchars); + } + + strcat (ldtext, cExp); + return ldtext; +} + + +/*** +*int _$i10_output(_ULDOUBLE ld, +* int ndigits, +* unsigned output_flags, +* FOS *fos) - output conversion of a 10-byte _ULDOUBLE +* +*Purpose: +* Fill in a FOS structure for a given _ULDOUBLE +* +*Entry: +* _ULDOUBLE ld: The long double to be converted into a string +* int ndigits: number of digits allowed in the output format. +* unsigned output_flags: The following flags can be used: +* SO_FFORMAT: Indicates 'f' format +* (default is 'e' format) +* FOS *fos: the structure that i10_output will fill in +* +*Exit: +* modifies *fos +* return 1 if original number was ok, 0 otherwise (infinity, NaN, etc) +* +*Exceptions: +* +*******************************************************************************/ + + +int $I10_OUTPUT(_ULDOUBLE ld, int ndigits, + unsigned output_flags, FOS *fos) +{ + u_short expn; + u_long manhi,manlo; + u_short sign; + + /* useful constants (see algorithm explanation below) */ + u_short const log2hi = 0x4d10; + u_short const log2lo = 0x4d; + u_short const log4hi = 0x9a; + u_long const c = 0x134312f4; +#if defined(L_END) + _ULDBL12 ld12_one_tenth = { + {0xcc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0xcc,0xcc,0xcc,0xcc,0xfb,0x3f} + }; +#elif defined(B_END) + _ULDBL12 ld12_one_tenth = { + {0x3f,0xfb,0xcc,0xcc,0xcc,0xcc, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc} + }; +#endif + + _ULDBL12 ld12; /* space for a 12-byte long double */ + _ULDBL12 tmp12; + u_short hh,ll; /* the bytes of the exponent grouped in 2 words*/ + u_short mm; /* the two MSBytes of the mantissa */ + s_long r; /* the corresponding power of 10 */ + s_short ir; /* ir = floor(r) */ + int retval = 1; /* assume valid number */ + char round; /* an additional character at the end of the string */ + char *p; + int i; + int ub_exp; + int digcount; + + /* grab the components of the long double */ + expn = *U_EXP_LD(&ld); + manhi = *UL_MANHI_LD(&ld); + manlo = *UL_MANLO_LD(&ld); + sign = expn & MSB_USHORT; + expn &= 0x7fff; + + if (sign) + fos->sign = '-'; + else + fos->sign = ' '; + + if (expn==0 && manhi==0 && manlo==0) { + PUT_ZERO_FOS(fos); + return 1; + } + + if (expn == 0x7fff) { + fos->exp = 1; /* set a positive exponent for proper output */ + + /* check for special cases */ + if (_IS_MAN_SNAN(sign, manhi, manlo)) { + /* signaling NAN */ + STRCPY(fos->man,SNAN_STR); + fos->ManLen = SNAN_STR_LEN; + retval = 0; + } + else if (_IS_MAN_IND(sign, manhi, manlo)) { + /* indefinite */ + STRCPY(fos->man,IND_STR); + fos->ManLen = IND_STR_LEN; + retval = 0; + } + else if (_IS_MAN_INF(sign, manhi, manlo)) { + /* infinity */ + STRCPY(fos->man,INF_STR); + fos->ManLen = INF_STR_LEN; + retval = 0; + } + else { + /* quiet NAN */ + STRCPY(fos->man,QNAN_STR); + fos->ManLen = QNAN_STR_LEN; + retval = 0; + } + } + else { + /* + * Algorithm for the decoding of a valid real number x + * + * In the following INT(r) is the largest integer less than or + * equal to r (i.e. r rounded toward -infinity). We want a result + * r equal to 1 + log(x), because then x = mantissa + * * 10^(INT(r)) so that .1 <= mantissa < 1. Unfortunately, + * we cannot compute s exactly so we must alter the procedure + * slightly. We will instead compute an estimate r of 1 + + * log(x) which is always low. This will either result + * in the correctly normalized number on the top of the stack + * or perhaps a number which is a factor of 10 too large. We + * will then check to see that if x is larger than one + * and if so multiply x by 1/10. + * + * We will use a low precision (fixed point 24 bit) estimate + * of of 1 + log base 10 of x. We have approximately .mm + * * 2^hhll on the top of the stack where m, h, and l represent + * hex digits, mm represents the high 2 hex digits of the + * mantissa, hh represents the high 2 hex digits of the exponent, + * and ll represents the low 2 hex digits of the exponent. Since + * .mm is a truncated representation of the mantissa, using it + * in this monotonically increasing polynomial approximation + * of the logarithm will naturally give a low result. Let's + * derive a formula for a lower bound r on 1 + log(x): + * + * .4D104D42H < log(2)=.30102999...(base 10) < .4D104D43H + * .9A20H < log(4)=.60205999...(base 10) < .9A21H + * + * 1/2 <= .mm < 1 + * ==> log(.mm) >= .mm * log(4) - log(4) + * + * Substituting in truncated hex constants in the formula above + * gives r = 1 + .4D104DH * hhll. + .9AH * .mm - .9A21H. Now + * multiplication of hex digits 5 and 6 of log(2) by ll has an + * insignificant effect on the first 24 bits of the result so + * it will not be calculated. This gives the expression r = + * 1 + .4D10H * hhll. + .4DH * .hh + .9A * .mm - .9A21H. + * Finally we must add terms to our formula to subtract out the + * effect of the exponent bias. We obtain the following formula: + * + * (implied decimal point) + * < >.< > + * |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|0|0|0|0|0|0|0|0|0|0| + * |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0| + * + < 1 > + * + < .4D10H * hhll. > + * + < .00004DH * hh00. > + * + < .9AH * .mm > + * - < .9A21H > + * - < .4D10H * 3FFEH > + * - < .00004DH * 3F00H > + * + * ==> r = .4D10H * hhll. + .4DH * .hh + .9AH * .mm - 1343.12F4H + * + * The difference between the lower bound r and the upper bound + * s is calculated as follows: + * + * .937EH < 1/ln(10)-log(1/ln(4))=.57614993...(base 10) < .937FH + * + * 1/2 <= .mm < 1 + * ==> log(.mm) <= .mm * log(4) - [1/ln(10) - log(1/ln(4))] + * + * so tenatively s = r + log(4) - [1/ln(10) - log(1/ln(4))], + * but we must also add in terms to ensure we will have an upper + * bound even after the truncation of various values. Because + * log(2) * hh00. is truncated to .4D104DH * hh00. we must + * add .0043H, because log(2) * ll. is truncated to .4D10H * + * ll. we must add .0005H, because <mantissa> * log(4) is + * truncated to .mm * .9AH we must add .009AH and .0021H. + * + * Thus s = r - .937EH + .9A21H + .0043H + .0005H + .009AH + .0021H + * = r + .07A6H + * ==> s = .4D10H * hhll. + .4DH * .hh + .9AH * .mm - 1343.0B4EH + * + * r is equal to 1 + log(x) more than (10000H - 7A6H) / + * 10000H = 97% of the time. + * + * In the above formula, a u_long is use to accomodate r, and + * there is an implied decimal point in the middle. + */ + + hh = expn >> 8; + ll = expn & (u_short)0xff; + mm = (u_short) (manhi >> 24); + r = (s_long)log2hi*(s_long)expn + log2lo*hh + log4hi*mm - c; + ir = (s_short)(r >> 16); + + /* + * + * We stated that we wanted to normalize x so that + * + * .1 <= x < 1 + * + * This was a slight oversimplification. Actually we want a + * number which when rounded to 16 significant digits is in the + * desired range. To do this we must normalize x so that + * + * .1 - 5*10^(-18) <= x < 1 - 5*10^(-17) + * + * and then round. + * + * If we had f = INT(1+log(x)) we could multiply by 10^(-f) + * to get x into the desired range. We do not quite have + * f but we do have INT(r) from the last step which is equal + * to f 97% of the time and 1 less than f the rest of the time. + * We can multiply by 10^-[INT(r)] and if the result is greater + * than 1 - 5*10^(-17) we can then multiply by 1/10. This final + * result will lie in the proper range. + */ + + /* convert _ULDOUBLE to _ULDBL12) */ + *U_EXP_12(&ld12) = expn; + *UL_MANHI_12(&ld12) = manhi; + *UL_MANLO_12(&ld12) = manlo; + *U_XT_12(&ld12) = 0; + + /* multiply by 10^(-ir) */ + __multtenpow12(&ld12,-ir,1); + + /* if ld12 >= 1.0 then divide by 10.0 */ + if (*U_EXP_12(&ld12) >= 0x3fff) { + ir++; + __ld12mul(&ld12,&ld12_one_tenth); + } + + fos->exp = ir; + if (output_flags & SO_FFORMAT){ + /* 'f' format, add exponent to ndigits */ + ndigits += ir; + if (ndigits <= 0) { + /* return 0 */ + PUT_ZERO_FOS(fos); + return 1; + } + } + if (ndigits > MAX_MAN_DIGITS) + ndigits = MAX_MAN_DIGITS; + + ub_exp = *U_EXP_12(&ld12) - 0x3ffe; /* unbias exponent */ + *U_EXP_12(&ld12) = 0; + + /* + * Now the mantissa has to be converted to fixed point. + * Then we will use the MSB of ld12 for generating + * the decimal digits. The next 11 bytes will hold + * the mantissa (after it has been converted to + * fixed point). + */ + + for (i=0;i<8;i++) + __shl_12(&ld12); /* make space for an extra byte, + in case we shift right later */ + if (ub_exp < 0) { + int shift_count = (-ub_exp) & 0xff; + for (;shift_count>0;shift_count--) + __shr_12(&ld12); + } + + p = fos->man; + for(digcount=ndigits+1;digcount>0;digcount--) { + tmp12 = ld12; + __shl_12(&ld12); + __shl_12(&ld12); + __add_12(&ld12,&tmp12); + __shl_12(&ld12); /* ld12 *= 10 */ + + /* Now we have the first decimal digit in the msbyte of exponent */ + *p++ = (char) (*UCHAR_12(&ld12,11) + '0'); + *UCHAR_12(&ld12,11) = 0; + } + + round = *(--p); + p--; /* p points now to the last character of the string + excluding the rounding digit */ + if (round >= '5') { + /* look for a non-9 digit starting from the end of string */ + for (;p>=fos->man && *p=='9';p--) { + *p = '0'; + } + if (p < fos->man){ + p++; + fos->exp ++; + } + (*p)++; + } + else { + /* remove zeros */ + for (;p>=fos->man && *p=='0';p--); + if (p < fos->man) { + /* return 0 */ + PUT_ZERO_FOS(fos); + return 1; + } + } + fos->ManLen = (char) (p - fos->man + 1); + fos->man[fos->ManLen] = '\0'; + } + return retval; +} |