int sdecode_number(const byte *str, int format, ref *np) { switch ( format & 0x170 ) { case num_int32: case num_int32 + 16: if ( (format & 31) == 0 ) { np->value.intval = sdecodelong(str, format); return t_integer; } else { np->value.realval = (double)sdecodelong(str, format) * binary_scale[format & 31]; return t_real; } case num_int16: if ( (format & 15) == 0 ) { np->value.intval = sdecodeshort(str, format); return t_integer; } else { np->value.realval = sdecodeshort(str, format) * binary_scale[format & 15]; return t_real; } case num_float: np->value.realval = sdecodefloat(str, format); return t_real; default: return_error(e_syntaxerror); /* invalid format?? */ } }
/* Decode a float. We assume that native floats occupy 32 bits. */ float sdecodefloat(const byte * p, int format) { bits32 lnum; float fnum; if ((format & ~(num_msb | num_lsb)) == num_float_native) { /* * Just read 4 bytes and interpret them as a float, ignoring * any indication of byte ordering. */ memcpy(&lnum, p, 4); fnum = *(float *)&lnum; } else { lnum = (bits32) sdecodelong(p, format); #if !arch_floats_are_IEEE { /* We know IEEE floats take 32 bits. */ /* Convert IEEE float to native float. */ int sign_expt = lnum >> 23; int expt = sign_expt & 0xff; int32_t mant = lnum & 0x7fffff; if (expt == 0 && mant == 0) fnum = 0; else { mant += 0x800000; fnum = (float)ldexp((float)mant, expt - 127 - 23); } if (sign_expt & 0x100) fnum = -fnum; } #else fnum = *(float *)&lnum; #endif } return fnum; }
/* Decode a float. We don't handle non-IEEE native representations yet. */ float sdecodefloat(register const byte *p, int format) { float fnum; if ( format != num_float_native ) { bits32 lnum = (bits32)sdecodelong(p, format); /* We know IEEE floats take 32 bits. */ #if !arch_floats_are_IEEE /* Convert IEEE float to native float. */ int sign_expt = lnum >> 23; int expt = sign_expt & 0xff; long mant = lnum & 0x7fffff; if ( expt == 0 && mant == 0 ) fnum = 0; else { mant += 0x800000; fnum = (float)ldexp((float)mant, expt - 127 - 24); } if ( sign_expt & 0x100 ) fnum = -fnum; #else fnum = *(float *)&lnum; #endif }