aboutsummaryrefslogtreecommitdiff
path: root/src/zebra.c
diff options
context:
space:
mode:
authortlatorre <tlatorre@uchicago.edu>2018-08-14 10:08:27 -0500
committertlatorre <tlatorre@uchicago.edu>2018-08-14 10:08:27 -0500
commit24c8bcfe7f76b20124e2862ea050f815c0f768e7 (patch)
treee5bdbd638a2c7f38f1c094cc9e95cbdfe05b9481 /src/zebra.c
parent0b7f199c0d93074484ea580504485a32dc29f5e2 (diff)
downloadsddm-24c8bcfe7f76b20124e2862ea050f815c0f768e7.tar.gz
sddm-24c8bcfe7f76b20124e2862ea050f815c0f768e7.tar.bz2
sddm-24c8bcfe7f76b20124e2862ea050f815c0f768e7.zip
move everything to src directory
Diffstat (limited to 'src/zebra.c')
-rw-r--r--src/zebra.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/zebra.c b/src/zebra.c
new file mode 100644
index 0000000..4ce51a2
--- /dev/null
+++ b/src/zebra.c
@@ -0,0 +1,219 @@
+#include "zebra.h"
+#include <stdio.h> /* for FILE */
+#include <stdlib.h> /* for size_t */
+#include "pack2b.h"
+#include <string.h> /* for memmove() */
+#include <stdint.h> /* for uint8_t, etc. */
+#include <errno.h> /* for strerror(), etc. */
+
+char zebra_err[256];
+
+zebraFile *zebra_open(const char *filename)
+{
+ FILE *f = fopen(filename, "r");
+
+ if (!f) {
+ sprintf(zebra_err, "failed to open '%s': %s", filename, strerror(errno));
+ return NULL;
+ }
+
+ zebraFile *z = (zebraFile *) malloc(sizeof(zebraFile));
+ z->f = f;
+ z->offset = 0;
+ z->lr_size = 0;
+ z->buf = NULL;
+ z->buf_size = 0;
+
+ return z;
+}
+
+int read_next_physical_record(zebraFile *z)
+{
+ /* Read the next physical record from the zebra file and append it to the
+ * buffer.
+ *
+ * Returns 0 on success, -1 on error, and 1 on EOF. */
+ uint8_t buf[48];
+ size_t nbytes;
+ uint32_t s0, s1, s2, s3, nwphr, nfast;
+
+ nbytes = fread(buf,4,8,z->f);
+
+ if (nbytes == 0) return 1;
+
+ if (nbytes != 8) {
+ sprintf(zebra_err, "expected %i words but only read %zu", 8, nbytes);
+ return -1;
+ }
+
+ s0 = unpacki32(buf);
+ s1 = unpacki32(buf+4*1);
+ s2 = unpacki32(buf+4*2);
+ s3 = unpacki32(buf+4*3);
+ nwphr = unpacki32(buf+4*4);
+ nfast = unpacki32(buf+7*4);
+
+ if (nwphr & (ZEBRA_EMERGENCY_STOP | ZEBRA_END_OF_RUN))
+ return 1;
+
+ nwphr &= ZEBRA_BLOCK_SIZE_MASK;
+
+ uint32_t words = nwphr*(1 + nfast) - 8;
+
+ if (s0 != ZEBRA_SIG0) {
+ sprintf(zebra_err, "invalid steering block stamp 0x%08x", s0);
+ return -1;
+ }
+
+ if (s1 != ZEBRA_SIG1) {
+ sprintf(zebra_err, "invalid steering block stamp 0x%08x", s1);
+ return -1;
+ }
+
+ if (s2 != ZEBRA_SIG2) {
+ sprintf(zebra_err, "invalid steering block stamp 0x%08x", s2);
+ return -1;
+ }
+
+ if (s3 != ZEBRA_SIG3) {
+ sprintf(zebra_err, "invalid steering block stamp 0x%08x", s3);
+ return -1;
+ }
+
+ z->buf = realloc(z->buf, z->buf_size+words*4);
+
+ nbytes = fread(z->buf+z->buf_size, 4, words, z->f);
+
+ z->buf_size += words*4;
+
+ if (nbytes != words) {
+ sprintf(zebra_err, "expected %i words but only read %zu", words, nbytes);
+ return -1;
+ }
+
+ return 0;
+}
+
+int get_bytes(zebraFile *z, size_t size)
+{
+ /* Read bytes from the zdab file until there are at least `size` words in
+ * the buffer.
+ *
+ * Returns 0 on success, -1 on error, and 1 on EOF. */
+ int rv;
+
+ while ((z->buf_size - z->offset) < size*4) {
+ rv = read_next_physical_record(z);
+
+ if (rv == -1) {
+ return -1;
+ } else if (z->buf_size == 0 && rv == 1) {
+ /* EOF and there are no bytes left. */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int read_next_logical_record(zebraFile *z)
+{
+ /* Read the next logical record into the buffer.
+ *
+ * Returns 0 on success, -1 on error, and 1 on EOF. */
+ uint32_t size, type, nwtx, nwseg, nwtab, nwuh;
+
+ while (1) {
+ memmove(z->buf,z->buf+z->offset,z->buf_size-z->offset);
+ z->buf = realloc(z->buf, z->buf_size-z->offset);
+ z->buf_size -= z->offset;
+ z->offset = 0;
+
+ switch (get_bytes(z,1)) {
+ case 1:
+ return 1;
+ case -1:
+ return -1;
+ }
+ size = unpacki32(z->buf+z->offset);
+ z->offset += 4;
+
+ if (size == 0) continue;
+
+ switch (get_bytes(z,1)) {
+ case 1:
+ return 1;
+ case -1:
+ return -1;
+ }
+ type = unpacki32(z->buf+z->offset);
+ z->offset += 4;
+
+ switch (type) {
+ case 5:
+ case 6:
+ get_bytes(z,size-1);
+ z->offset += (size-1)*4;
+ continue;
+ case 1:
+ get_bytes(z,size);
+ z->offset += size*4;
+ continue;
+ }
+
+ z->lr_size = (size + 2)*4;
+ get_bytes(z,size);
+
+ nwtx = unpacki32(z->buf+z->offset+4*4);
+ nwseg = unpacki32(z->buf+z->offset+5*4);
+ nwtab = unpacki32(z->buf+z->offset+6*4);
+ nwuh = unpacki32(z->buf+z->offset+9*4);
+
+ z->offset += 10*4;
+
+ z->offset += nwtx*4;
+ z->offset += nwseg*4;
+ z->offset += nwtab*4;
+ z->offset += nwuh*4;
+
+ break;
+ }
+
+ return 0;
+}
+
+int next_bank(zebraFile *z, bank *b)
+{
+ int rv;
+ uint32_t io, noff;
+
+ if (z->offset == z->lr_size) {
+ rv = read_next_logical_record(z);
+ if (rv) return rv;
+ }
+
+ io = unpacki32(z->buf+z->offset);
+ z->offset += 4;
+
+ noff = io & 0xFFFF;
+
+ if (noff > 12) {
+ z->offset += (noff-12)*4;
+ }
+
+ unpack(z->buf+z->offset,"lllllllll",&b->next, &b->up, &b->orig, &b->number, &b->name, &b->num_links, &b->num_structural_links, &b->num_data_words, &b->status);
+ z->offset += 9*4;
+
+ b->data = (uint32_t *) (z->buf+z->offset);
+
+ z->offset += b->num_data_words*4;
+
+ return 0;
+}
+
+void zebra_close(zebraFile *z)
+{
+ fclose(z->f);
+ if (z->buf) free(z->buf);
+ free(z);
+}