blind-from-portable.c (3967B)
1 /* See LICENSE file for copyright and license details. */ 2 #define INCLUDE_UINT16 3 #include "common.h" 4 5 USAGE("[-s]") 6 7 static int strict = 1; 8 9 #define CONV(ITYPE, SITYPE, OTYPE, EXPONENT, HA2EXPONENT, FRACTION)\ 10 do {\ 11 static int cache_i = 0;\ 12 static ITYPE cache_in[] = {0, 0, 0, 0};\ 13 static OTYPE cache_out[] = {0, 0, 0, 0};\ 14 ITYPE exponent, fraction, signb;\ 15 SITYPE sexponent;\ 16 OTYPE ret, dexponent;\ 17 if (portable == cache_in[cache_i]) {\ 18 ret = cache_out[cache_i++];\ 19 cache_i &= 3;\ 20 return ret;\ 21 }\ 22 cache_in[cache_i] = portable;\ 23 signb = portable >> (EXPONENT + FRACTION);\ 24 exponent = (portable >> FRACTION) ^ (signb << EXPONENT);\ 25 fraction = portable & (((ITYPE)1 << FRACTION) - 1);\ 26 if (!exponent) {\ 27 if (!fraction) {\ 28 ret = (OTYPE)0.0;\ 29 } else {\ 30 sexponent = 1 - HA2EXPONENT - FRACTION;\ 31 dexponent = (OTYPE)sexponent;\ 32 ret = (OTYPE)fraction;\ 33 ret *= pow((OTYPE)2.0, dexponent);\ 34 }\ 35 } else if (exponent + 1 == (ITYPE)1 << EXPONENT) {\ 36 ret = (OTYPE)(fraction ? NAN : INFINITY);\ 37 } else {\ 38 fraction |= (ITYPE)1 << FRACTION;\ 39 sexponent = (SITYPE)exponent;\ 40 sexponent -= HA2EXPONENT + FRACTION;\ 41 dexponent = (OTYPE)sexponent;\ 42 ret = (OTYPE)fraction;\ 43 ret *= pow((OTYPE)2.0, dexponent);\ 44 }\ 45 ret = signb ? -ret : ret;\ 46 cache_out[cache_i++] = ret;\ 47 cache_i &= 3;\ 48 return ret;\ 49 } while (0) 50 51 #define PROCESS_FLOAT(ITYPE, OTYPE, BITS)\ 52 do {\ 53 size_t i, n;\ 54 ITYPE *ibuf = (ITYPE *)(stream->buf);\ 55 OTYPE *obuf = sizeof(ITYPE) == sizeof(OTYPE) ? (OTYPE *)(stream->buf)\ 56 : alloca(sizeof(stream->buf) / sizeof(ITYPE) * sizeof(OTYPE));\ 57 strict *= !USING_BINARY##BITS;\ 58 if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\ 59 eprintf("-s is supported not on this machine\n");\ 60 if (stream->endian == HOST && !strict) {\ 61 esend_stream(stream, STDOUT_FILENO, "<stdout>");\ 62 break;\ 63 }\ 64 do {\ 65 n = stream->ptr / sizeof(ITYPE);\ 66 if (strict) {\ 67 for (i = 0; i < n; i++)\ 68 obuf[i] = conv_##OTYPE(letoh(ibuf[i]));\ 69 } else {\ 70 for (i = 0; i < n; i++)\ 71 obuf[i] = *(OTYPE *)&(ITYPE){letoh(ibuf[i])};\ 72 }\ 73 ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE), "<stdout>");\ 74 n *= sizeof(ITYPE);\ 75 memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ 76 } while (eread_stream(stream, SIZE_MAX));\ 77 if (stream->ptr)\ 78 eprintf("%s: incomplete frame\n", stream->file);\ 79 } while (0) 80 81 #define PROCESS_INTEGER(TYPE)\ 82 do {\ 83 size_t i, n;\ 84 TYPE *buf = (TYPE *)(stream->buf);\ 85 if (stream->endian == HOST) {\ 86 esend_stream(stream, STDOUT_FILENO, "<stdout>");\ 87 break;\ 88 }\ 89 do {\ 90 n = stream->ptr / sizeof(TYPE);\ 91 for (i = 0; i < n; i++)\ 92 buf[i] = letoh(buf[i]);\ 93 n *= sizeof(TYPE);\ 94 ewriteall(STDOUT_FILENO, buf, n, "<stdout>");\ 95 memmove(stream->buf, stream->buf + n, stream->ptr -= n);\ 96 } while (eread_stream(stream, SIZE_MAX));\ 97 if (stream->ptr)\ 98 eprintf("%s: incomplete frame\n", stream->file);\ 99 } while (0) 100 101 static double conv_double(uint64_t portable) {CONV(uint64_t, int64_t, double, 11, 1023, 52);} 102 static float conv_float (uint32_t portable) {CONV(uint32_t, int32_t, float, 8, 127, 23);} 103 104 static void process_lf (struct stream *stream) {PROCESS_FLOAT(uint64_t, double, 64);} 105 static void process_f (struct stream *stream) {PROCESS_FLOAT(uint32_t, float, 32);} 106 static void process_u16(struct stream *stream) {PROCESS_INTEGER(uint16_t);} 107 108 int 109 main(int argc, char *argv[]) 110 { 111 struct stream stream; 112 void (*process)(struct stream *stream); 113 114 ARGBEGIN { 115 case 's': 116 strict = 0; 117 break; 118 default: 119 usage(); 120 } ARGEND; 121 122 if (argc) 123 usage(); 124 125 eopen_stream(&stream, NULL); 126 #if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN) 127 if (stream.endian == LITTLE) 128 stream.endian = HOST; 129 #elif defined(HOST_ENDIAN_IS_BIG_ENDIAN) 130 if (stream.endian == BIG) 131 stream.endian = HOST; 132 #endif 133 134 SELECT_PROCESS_FUNCTION(&stream); 135 fprint_stream_head(stdout, &stream); 136 efflush(stdout, "<stdout>"); 137 process(&stream); 138 return 0; 139 }