| blind-to-portable.c - blind - suckless command-line video editing utility | |
| git clone git://git.suckless.org/blind | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| blind-to-portable.c (4415B) | |
| --- | |
| 1 /* See LICENSE file for copyright and license details. */ | |
| 2 #define INCLUDE_UINT16 | |
| 3 #include "common.h" | |
| 4 | |
| 5 /* Disable warnings in <math.h> */ | |
| 6 #if defined(__clang__) | |
| 7 # pragma clang diagnostic ignored "-Wdouble-promotion" | |
| 8 # pragma clang diagnostic ignored "-Wconversion" | |
| 9 #endif | |
| 10 | |
| 11 USAGE("[-s]") | |
| 12 | |
| 13 static int strict = 1; | |
| 14 | |
| 15 #define CONV(ITYPE, OTYPE, SOTYPE, EXPONENT, HA2EXPONENT, FRACTION)\ | |
| 16 do {\ | |
| 17 static int cache_i = 0;\ | |
| 18 static ITYPE cache_in[] = {0, 0, 0, 0};\ | |
| 19 static OTYPE cache_out[] = {0, 0, 0, 0};\ | |
| 20 OTYPE signb, fraction, ret;\ | |
| 21 SOTYPE exponent;\ | |
| 22 ITYPE u, dexponent;\ | |
| 23 if (host == cache_in[cache_i]) {\ | |
| 24 ret = cache_out[cache_i++];\ | |
| 25 cache_i &= 3;\ | |
| 26 return ret;\ | |
| 27 }\ | |
| 28 cache_in[cache_i] = host;\ | |
| 29 signb = (OTYPE)signbit(host);\ | |
| 30 u = signb ? -host : host;\ | |
| 31 if (g_isnan(host) || g_isinf(host)) {\ | |
| 32 ret = ((((OTYPE)1 << EXPONENT) - (OTYPE)1) << FR… | |
| 33 } else if (u == (ITYPE)0.0) {\ | |
| 34 ret = 0;\ | |
| 35 } else {\ | |
| 36 dexponent = log2(u);\ | |
| 37 exponent = (SOTYPE)dexponent;\ | |
| 38 if (u == pow((ITYPE)2.0, (ITYPE)exponent)) {\ | |
| 39 exponent += HA2EXPONENT;\ | |
| 40 fraction = 0;\ | |
| 41 } else {\ | |
| 42 /* TODO subnormals are a bit rounded off… | |
| 43 u *= pow((ITYPE)2.0, (ITYPE)(FRACTION + … | |
| 44 fraction = (OTYPE)u;\ | |
| 45 while (fraction >= (OTYPE)2 << FRACTION)… | |
| 46 fraction >>= 1;\ | |
| 47 exponent += 1;\ | |
| 48 }\ | |
| 49 fraction &= ((OTYPE)1 << FRACTION) - 1;\ | |
| 50 exponent += HA2EXPONENT - 1;\ | |
| 51 }\ | |
| 52 if (exponent < 1) {\ | |
| 53 /* TODO subnormal result */\ | |
| 54 exponent = 0;\ | |
| 55 fraction = 0;\ | |
| 56 } else if (exponent >= ((SOTYPE)1 << EXPONENT) -… | |
| 57 exponent = ((SOTYPE)1 << EXPONENT) - 1;\ | |
| 58 fraction = 0;\ | |
| 59 }\ | |
| 60 ret = ((OTYPE)exponent << FRACTION) + fraction;\ | |
| 61 }\ | |
| 62 ret |= signb << (FRACTION + EXPONENT);\ | |
| 63 cache_out[cache_i++] = ret;\ | |
| 64 cache_i &= 3;\ | |
| 65 return ret;\ | |
| 66 } while (0) | |
| 67 | |
| 68 #define PROCESS_FLOAT(ITYPE, OTYPE, BITS)\ | |
| 69 do {\ | |
| 70 size_t i, n;\ | |
| 71 ITYPE *ibuf = (ITYPE *)(stream->buf);\ | |
| 72 OTYPE *obuf = sizeof(ITYPE) == sizeof(OTYPE) ? (OTYPE *)… | |
| 73 : alloca(sizeof(stream->buf) / sizeof(ITYPE) * s… | |
| 74 strict *= !USING_BINARY##BITS;\ | |
| 75 if (!strict && sizeof(ITYPE) != sizeof(OTYPE))\ | |
| 76 eprintf("-s is supported not on this machine\n")… | |
| 77 if (stream->endian == LITTLE && !strict) {\ | |
| 78 esend_stream(stream, STDOUT_FILENO, "<stdout>");\ | |
| 79 break;\ | |
| 80 }\ | |
| 81 do {\ | |
| 82 n = stream->ptr / sizeof(ITYPE);\ | |
| 83 if (strict) {\ | |
| 84 for (i = 0; i < n; i++)\ | |
| 85 obuf[i] = htole(conv_##ITYPE(ibu… | |
| 86 } else {\ | |
| 87 for (i = 0; i < n; i++)\ | |
| 88 obuf[i] = htole(*(OTYPE *)&ibuf[… | |
| 89 }\ | |
| 90 ewriteall(STDOUT_FILENO, obuf, n * sizeof(OTYPE)… | |
| 91 n *= sizeof(ITYPE);\ | |
| 92 memmove(stream->buf, stream->buf + n, stream->pt… | |
| 93 } while (eread_stream(stream, SIZE_MAX));\ | |
| 94 if (stream->ptr)\ | |
| 95 eprintf("%s: incomplete frame\n", stream->file);\ | |
| 96 } while (0) | |
| 97 | |
| 98 #define PROCESS_INTEGER(TYPE)\ | |
| 99 do {\ | |
| 100 size_t i, n;\ | |
| 101 TYPE *buf = (TYPE *)(stream->buf);\ | |
| 102 if (stream->endian == LITTLE) {\ | |
| 103 esend_stream(stream, STDOUT_FILENO, "<stdout>");\ | |
| 104 break;\ | |
| 105 }\ | |
| 106 do {\ | |
| 107 n = stream->ptr / sizeof(TYPE);\ | |
| 108 for (i = 0; i < n; i++)\ | |
| 109 buf[i] = htole(buf[i]);\ | |
| 110 n *= sizeof(TYPE);\ | |
| 111 ewriteall(STDOUT_FILENO, buf, n, "<stdout>");\ | |
| 112 memmove(stream->buf, stream->buf + n, stream->pt… | |
| 113 } while (eread_stream(stream, SIZE_MAX));\ | |
| 114 if (stream->ptr)\ | |
| 115 eprintf("%s: incomplete frame\n", stream->file);\ | |
| 116 } while (0) | |
| 117 | |
| 118 static uint64_t conv_double(double host) {CONV(double, uint64_t, int64_t… | |
| 119 static uint32_t conv_float (float host) {CONV(float, uint32_t, int32_t… | |
| 120 | |
| 121 static void process_lf (struct stream *stream) {PROCESS_FLOAT(double, ui… | |
| 122 static void process_f (struct stream *stream) {PROCESS_FLOAT(float, ui… | |
| 123 static void process_u16(struct stream *stream) {PROCESS_INTEGER(uint16_t… | |
| 124 | |
| 125 int | |
| 126 main(int argc, char *argv[]) | |
| 127 { | |
| 128 struct stream stream; | |
| 129 void (*process)(struct stream *stream); | |
| 130 | |
| 131 ARGBEGIN { | |
| 132 case 's': | |
| 133 strict = 0; | |
| 134 break; | |
| 135 default: | |
| 136 usage(); | |
| 137 } ARGEND; | |
| 138 | |
| 139 if (argc) | |
| 140 usage(); | |
| 141 | |
| 142 eopen_stream(&stream, NULL); | |
| 143 #if defined(HOST_ENDIAN_IS_LITTLE_ENDIAN) | |
| 144 if (stream.endian == HOST) | |
| 145 stream.endian = LITTLE; | |
| 146 #elif defined(HOST_ENDIAN_IS_BIG_ENDIAN) | |
| 147 if (stream.endian == HOST) | |
| 148 stream.endian = BIG; | |
| 149 #endif | |
| 150 | |
| 151 SELECT_PROCESS_FUNCTION(&stream); | |
| 152 fprint_stream_head(stdout, &stream); | |
| 153 efflush(stdout, "<stdout>"); | |
| 154 process(&stream); | |
| 155 return 0; | |
| 156 } |