10 #include "u8-mbtouc.h"
16 #define STR(x) XSTR(x)
17 #define WHERE __FILE__":" STR(__LINE__)
23 memcpy(&x, &data[pos], 4);
32 memcpy(&x, &data[pos], 8);
47 match_u32_assert(uint32_t x, const char *where)
49 unsigned int y = get_u32();
52 fprintf(stderr, "%s: 0x%x: expected i%u, got i%u\n", where, pos - 4, x, y);
56 #define match_u32_assert(x) match_u32_assert(x, WHERE)
61 if (pos < n && data[pos] == b)
71 match_byte_assert(uint8_t b, const char *where)
75 fprintf(stderr, "%s: 0x%x: expected %02x, got %02x\n", where, pos, b, data[pos]);
79 #define match_byte_assert(b) match_byte_assert(b, WHERE)
82 all_ascii(const uint8_t *p)
85 if (*p < 32 || *p > 126)
91 all_utf8(const uint8_t *p)
93 size_t len = strlen ((char *) p);
94 for (size_t ofs = 0, mblen; ofs < len; ofs += mblen)
98 mblen = u8_mbtouc (&uc, p + ofs, len - ofs);
99 if (uc < 32 || uc == 127 || uc == 0xfffd)
106 get_fixed_string(int len, const char *where)
108 if (pos + len > n || !memchr(&data[pos], 0, len) || !all_utf8(&data[pos]))
110 fprintf(stderr, "%s: 0x%x: bad fixed-width string\n", where, pos);
113 char *s = (char *) &data[pos];
117 #define get_fixed_string(len) get_fixed_string(len, WHERE)
120 all_ascii2(const uint8_t *p, size_t n)
122 for (size_t i = 0; i < n; i++)
123 if (p[i] < 32 || p[i] > 126)
129 get_string(const char *where)
132 /*data[pos + 1] == 0 && data[pos + 2] == 0 && data[pos + 3] == 0*/
133 /*&& all_ascii(&data[pos + 4], data[pos])*/)
135 int len = data[pos] + data[pos + 1] * 256;
136 char *s = malloc(len + 1);
138 memcpy(s, &data[pos + 4], len);
145 fprintf(stderr, "%s: 0x%x: expected string\n", where, pos);
149 #define get_string() get_string(WHERE)
152 dump_raw(FILE *stream, int start, int end, const char *separator)
154 for (size_t i = start; i < end; )
161 && i + 4 + data[i] + data[i + 1] * 256 <= end
162 && all_ascii2(&data[i + 4], data[i] + data[i + 1] * 256))
164 fprintf(stream, "%s\"", separator);
165 fwrite(&data[i + 4], 1, data[i] + data[i + 1] * 256, stream);
166 fputs("\" ", stream);
168 i += 4 + data[i] + data[i + 1] * 256;
170 else if (i + 12 <= end
177 memcpy (&d, &data[i + 4], 8);
178 fprintf (stream, "F40.%d(%.*f)%s", data[i], data[i], d, separator);
181 else if (i + 12 <= end
188 memcpy (&d, &data[i + 4], 8);
189 fprintf (stream, "PCT40.%d(%.*f)%s", data[i], data[i], d, separator);
192 else if (i + 4 <= end
197 fprintf (stream, "i%d ", data[i]);
202 fprintf(stream, "%02x ", data[i]);
209 dump_source(int end, int count, int n_series, const char *name)
216 sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}};
218 for (int i = 0; i < n_series; i++)
220 printf (" series %d: \"%s\", %d values:\n ",
221 i, get_fixed_string(288), count);
222 for (int i = 0; i < count; i++)
224 double d = get_double();
231 printf (" %.*g", DBL_DIG, d);
240 char *name2 = get_string();
241 assert(!strcmp(name, name2));
243 printf ("\n %08x:", pos);
244 int n_more_series = get_u32();
245 if (n_series != n_more_series)
246 printf("different series counts: %d %d\n", n_series, n_more_series);
247 assert(n_more_series <= n_series);
248 printf (" %d series to come\n", n_more_series);
252 for (int i = 0; i < n_more_series; i++)
254 printf ("%08x:", pos);
255 printf (" \"%s\"", get_string());
256 int n_pairs = get_u32();
257 for (int j = 0; j < n_pairs; j++)
261 printf (" (%d, %d)", x, y);
268 printf ("\n%08x:", pos);
269 int n_strings = get_u32();
270 assert(n_strings == max1 + 1);
271 printf (" %d strings\n", n_strings);
273 char **strings = malloc(n_strings * sizeof *strings);
274 for (int i = 0; i < n_strings; i++)
276 int frequency = get_u32();
277 char *s = get_string();
278 printf ("%d: \"%s\" (%d)\n", i, s, frequency);
285 printf("Strings:\n");
286 for (int i = 0; i < n_more_series; i++)
288 printf (" \"%s\"\n", get_string());
289 int n_pairs = get_u32();
290 for (int j = 0; j < n_pairs; j++)
295 printf (" %d: \"%s\"\n", x, strings[y]);
303 main(int argc, char **argv)
308 if (isatty(STDIN_FILENO))
310 fprintf(stderr, "redirect stdin from a .bin file\n");
313 if (fstat(STDIN_FILENO, &s))
325 if (read(STDIN_FILENO, data, n) != n)
332 match_byte_assert(0);
333 int version = data[pos];
334 if (!match_byte(0xaf))
335 match_byte_assert(0xb0);
336 int n_sources = data[pos++];
337 match_byte_assert(0);
339 match_u32_assert(s.st_size);
340 printf ("%d sources\n", n_sources);
344 int offset, count, n_series;
348 for (int i = 0; i < n_sources; i++)
350 int count = get_u32();
351 int n_series = get_u32();
352 int offset = get_u32();
353 char *name = get_fixed_string(version == 0xb0 ? 64 : 28);
354 int dunno = version == 0xb0 ? get_u32() : 0;
355 printf ("source %d: %d series, %d observations per series, offset %08x, \"%s\", %x\n",
356 i, n_series, count, offset, name, dunno);
357 sources[i].offset = offset;
358 sources[i].count = count;
359 sources[i].n_series = n_series;
360 sources[i].name = name;
363 for (int i = 0; i < n_sources; i++)
365 if (pos != sources[i].offset)
367 fprintf (stderr, "pos=0x%x expected=0x%x reading source %d\n", pos, sources[i].offset, i);
370 dump_source(i + 1 >= n_sources ? n : sources[i + 1].offset, sources[i].count, sources[i].n_series, sources[i].name);