15 #define STR(x) XSTR(x)
16 #define WHERE __FILE__":" STR(__LINE__)
22 memcpy(&x, &data[pos], 4);
31 memcpy(&x, &data[pos], 8);
46 match_u32_assert(uint32_t x, const char *where)
48 unsigned int y = get_u32();
51 fprintf(stderr, "%s: 0x%x: expected i%u, got i%u\n", where, pos - 4, x, y);
55 #define match_u32_assert(x) match_u32_assert(x, WHERE)
60 if (pos < n && data[pos] == b)
70 match_byte_assert(uint8_t b, const char *where)
74 fprintf(stderr, "%s: 0x%x: expected %02x, got %02x\n", where, pos, b, data[pos]);
78 #define match_byte_assert(b) match_byte_assert(b, WHERE)
81 all_ascii(const uint8_t *p)
84 if (*p < 32 || *p > 126)
90 get_fixed_string(int len, const char *where)
92 if (pos + len > n || !memchr(&data[pos], 0, len) || !all_ascii(&data[pos]))
94 fprintf(stderr, "%s: 0x%x: bad fixed-width string\n", where, pos);
97 char *s = (char *) &data[pos];
101 #define get_fixed_string(len) get_fixed_string(len, WHERE)
104 all_ascii2(const uint8_t *p, size_t n)
106 for (size_t i = 0; i < n; i++)
107 if (p[i] < 32 || p[i] > 126)
113 get_string(const char *where)
116 /*data[pos + 1] == 0 && data[pos + 2] == 0 && data[pos + 3] == 0*/
117 /*&& all_ascii(&data[pos + 4], data[pos])*/)
119 int len = data[pos] + data[pos + 1] * 256;
120 char *s = malloc(len + 1);
122 memcpy(s, &data[pos + 4], len);
129 fprintf(stderr, "%s: 0x%x: expected string\n", where, pos);
133 #define get_string() get_string(WHERE)
136 dump_raw(FILE *stream, int start, int end, const char *separator)
138 for (size_t i = start; i < end; )
145 && i + 4 + data[i] + data[i + 1] * 256 <= end
146 && all_ascii2(&data[i + 4], data[i] + data[i + 1] * 256))
148 fprintf(stream, "%s\"", separator);
149 fwrite(&data[i + 4], 1, data[i] + data[i + 1] * 256, stream);
150 fputs("\" ", stream);
152 i += 4 + data[i] + data[i + 1] * 256;
154 else if (i + 12 <= end
161 memcpy (&d, &data[i + 4], 8);
162 fprintf (stream, "F40.%d(%.*f)%s", data[i], data[i], d, separator);
165 else if (i + 12 <= end
172 memcpy (&d, &data[i + 4], 8);
173 fprintf (stream, "PCT40.%d(%.*f)%s", data[i], data[i], d, separator);
176 else if (i + 4 <= end
181 fprintf (stream, "i%d ", data[i]);
186 fprintf(stream, "%02x ", data[i]);
193 dump_source(int end, int count, int n_series)
200 sysmis = {.b = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff}};
202 for (int i = 0; i < n_series; i++)
204 printf (" series %d: \"%s\"\n ", i, get_fixed_string(288));
205 for (int i = 0; i < count; i++)
207 double d = get_double();
214 printf (" %.*g", DBL_DIG, d);
222 printf ("\n %08x: (%d sysmis)", pos, n_sysmis);
223 printf (" %d", get_u32());
224 printf (", \"%s\"\n", get_string());
226 printf ("\n %08x:", pos);
227 int n_more_series = get_u32();
228 printf (" %d series to come\n", n_more_series);
230 for (int i = 0; i < n_more_series; i++)
232 printf ("%08x:", pos);
233 printf (" \"%s\"", get_string());
234 int n_pairs = get_u32();
235 for (int j = 0; j < n_pairs; j++)
239 printf (" (%d,%d)", x, y);
244 printf ("\n%08x:", pos);
245 int n_strings = get_u32();
246 printf (" %d strings\n", n_strings);
247 for (int i = 0; i < n_strings; i++)
250 char *s = get_string();
251 printf ("%d: \"%s\" (%d)\n", i, s, x);
257 main(int argc, char **argv)
262 if (isatty(STDIN_FILENO))
264 fprintf(stderr, "redirect stdin from a .bin file\n");
267 if (fstat(STDIN_FILENO, &s))
279 if (read(STDIN_FILENO, data, n) != n)
286 match_byte_assert(0);
287 int version = data[pos];
288 if (!match_byte(0xaf))
289 match_byte_assert(0xb0);
290 int n_sources = data[pos++];
291 match_byte_assert(0);
293 match_u32_assert(s.st_size);
294 printf ("%d sources\n", n_sources);
298 int offset, count, n_series;
301 for (int i = 0; i < n_sources; i++)
303 int count = get_u32();
304 int n_series = get_u32();
305 int offset = get_u32();
306 char *name = get_fixed_string(version == 0xb0 ? 64 : 28);
307 int dunno = version == 0xb0 ? get_u32() : 0;
308 printf ("source %d: %d series, %d observations per series, offset %08x, \"%s\", %x\n",
309 i, n_series, count, offset, name, dunno);
310 sources[i].offset = offset;
311 sources[i].count = count;
312 sources[i].n_series = n_series;
315 for (int i = 0; i < n_sources; i++)
317 if (pos != sources[i].offset)
319 fprintf (stderr, "pos=0x%x expected=0x%x reading source %d\n", pos, sources[i].offset, i);
322 dump_source(i + 1 >= n_sources ? n : sources[i + 1].offset, sources[i].count, sources[i].n_series);