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 } |