Commit Diff


commit - 780459fb4692655b2d9c001d8f0f992c21c9bf46
commit + ec716a83243eeb924f17d2d31a4401c98681c673
blob - fa63cc7bf930d8d95f48b8331ce6579de841d6f9
blob + b4fe389695079fcfcfca811492f94f2ea77ed2dc
--- Makefile
+++ Makefile
@@ -1,4 +1,4 @@
-OBJ = parse.o lex.o main.o
+OBJ = parse.o lex.o gen.o main.o
 
 all: destruct
 
@@ -6,7 +6,7 @@ run: destruct
 	./destruct < test.txt
 
 clean:
-	rm -f destruct destruct.inc y.tab.h *.o
+	rm -f destruct destruct.inc y.tab.h *.o *.core
 
 destruct: destruct.inc ${OBJ}
 	${CC} -o $@ ${OBJ}
blob - /dev/null
blob + 3ee1a951bf1c57a144bb0c4d42ad311a08dc983b (mode 644)
--- /dev/null
+++ .gitignore
@@ -0,0 +1,6 @@
+destruct
+destruct.inc
+y.tab.h
+*.o
+*.swp
+*.core
blob - 21b050e2a21535b5b02681de5aa6b48b6305eb1b
blob + e9b7907d4c124ac1ac36ca3bea04d40efa4bdebb
--- main.c
+++ main.c
@@ -1,419 +1,75 @@
+#include <unistd.h>
 #include <string.h>
-#include <stdlib.h>
 #include <stdio.h>
 #include <err.h>
 #include "ast.h"
 
-static struct structure **file;
+#define DST_LITTLE_ENDIAN 1234
+#define DST_BIG_ENDIAN 4321
+#define DST_DEFAULT_ENDIAN DST_LITTLE_ENDIAN
+
+void gen (struct structure **, int from, int to);
 struct structure **parse (void);
 
-struct structure *get_struct (const char *name)
+int parse_endian2 (const char *s)
 {
-	for (struct structure **i = file; *i != NULL; ++i) {
-		struct structure *st = *i;
-		if (strcmp (name, st->name) == 0)
-			return st;
+	if (strcmp (s, "little") == 0) {
+		return DST_LITTLE_ENDIAN;
+	} else if (strcmp (s, "big") == 0) {
+		return DST_BIG_ENDIAN;
+	} else {
+		errx (1, "invalid endianness: %s", s);
 	}
-	errx (1, "invalid struct: %s", name);
 }
 
-size_t size_of_struct (struct structure *st);
-size_t size_of_union (struct uitem **u);
-size_t size_of (struct type *ty)
+void parse_endian (char *s, int *from, int *to)
 {
-	switch (ty->type) {
-	case T_I8:
-	case T_U8:
-		return 1;
-	case T_I16:
-	case T_U16:
-		return 2;
-	case T_I32:
-	case T_U32:
-		return 4;
-	case T_I64:
-	case T_U64:
-		return 8;
-	case T_ARRAY:
-		return ty->len * size_of (ty->inner);
-	case T_NAME:
-		return size_of_struct (get_struct (ty->name));
-	case T_STRUCT:
-		return size_of_struct (ty->st);
-	case T_UNION:
-		return size_of_union (ty->un);
-	}
-}
+	char *colon;
 
-size_t size_of_struct (struct structure *st)
-{
-	size_t sz = 0;
+	colon = strchr (s, ':');
 
-	for (struct item **i = st->items; *i != NULL; ++i) {
-		sz += size_of ((*i)->type);
+	if (colon != NULL) {
+		*colon = '\0';
+		*from = parse_endian2 (s);
+		*to = parse_endian2 (colon + 1);
+		*colon = ':';
+	} else {
+		*from = *to = parse_endian2 (s);
 	}
-
-	return sz;
 }
 
-size_t size_of_union (struct uitem **u)
+int usage (void)
 {
-	size_t sz = 0;
-
-	for (struct uitem **i = u; *i != NULL; ++i) {
-		size_t s = size_of ((*i)->type);
-		if (s > sz)
-			sz = s;
-	}
-
-	return sz;
+	fputs ("usage: destruct [-e endian[:endian]]\n", stderr);
+	return 1;
 }
 
-size_t align_of_struct (struct structure *st);
-size_t align_of_union (struct uitem **u);
-size_t align_of (struct type *ty)
+int main (int argc, char *argv[])
 {
-	switch (ty->type) {
-	case T_I8:
-	case T_U8:
-	case T_I16:
-	case T_U16:
-	case T_I32:
-	case T_U32:
-	case T_I64:
-	case T_U64:
-		return size_of (ty);
-	case T_ARRAY:
-		return align_of (ty->inner);
-	case T_NAME:
-		return align_of_struct (get_struct (ty->name));
-	case T_STRUCT:
-		return align_of_struct (ty->st);
-	case T_UNION:
-		return align_of_union (ty->un);
-	}
-}
+	struct structure **file;
+	int from = DST_DEFAULT_ENDIAN, to = DST_DEFAULT_ENDIAN;
+	int option;
 
-size_t align_of_struct (struct structure *st)
-{
-	size_t al = 0;
-
-	for (struct item **i = st->items; *i != NULL; ++i) {
-		size_t a = align_of ((*i)->type);
-		if (a > al)
-			al = a;
-	}
-
-	return al;
-}
-
-size_t align_of_union (struct uitem **u)
-{
-	size_t al = 0;
-
-	for (struct uitem **i = u; *i != NULL; ++i) {
-		size_t a = align_of ((*i)->type);
-		if (a > al)
-			al = a;
-	}
-
-	return al;
-}
-
-size_t align (size_t offset, size_t alignment)
-{
-	return (offset + alignment - 1) & -alignment;
-}
-
-void prindent (int ind)
-{
-	for (int i = 0; i < ind; ++i)
-		putchar ('\t');
-}
-
-void print_value (struct value *v)
-{
-	switch (v->type) {
-	case V_NAME:
-		printf ("%s", v->s);
-		break;
-	case V_INT:
-		printf ("%d", v->i);
-		break;
-	}
-}
-
-void print_cond (struct cond *co, const char *prefix)
-{
-	switch (co->type) {
-	case C_EQ:
-		printf ("%s%s == ", prefix, co->cmp.left);
-		print_value (co->cmp.right);
-		break;
-	}
-}
-
-void print_item2 (struct type *ty, const char *name, int indent)
-{
-	switch (ty->type) {
-	case T_I8:
-		printf ("int8_t %s", name);
-		break;
-	case T_I16:
-		printf ("int16_t %s", name);
-		break;
-	case T_I32:
-		printf ("int32_t %s", name);
-		break;
-	case T_I64:
-		printf ("int64_t %s", name);
-		break;
-	case T_U8:
-		printf ("uint8_t %s", name);
-		break;
-	case T_U16:
-		printf ("uint16_t %s", name);
-		break;
-	case T_U32:
-		printf ("uint32_t %s", name);
-		break;
-	case T_U64:
-		printf ("uint64_t %s", name);
-		break;
-	case T_ARRAY:
-		print_item2 (ty->inner, name, indent);
-		printf ("[%zu]", ty->len);
-		break;
-	case T_NAME:
-		printf ("struct %s %s", ty->name, name);
-		break;
-	case T_STRUCT:
-		printf ("struct {\n");
-
-		for (struct item **i = ty->st->items; *i != NULL; ++i) {
-			struct item *it = *i;
-			prindent (indent + 1);
-			print_item2 (it->type, it->name, indent + 1);
-			puts (";");
+	while ((option = getopt (argc, argv, "e:")) != -1) {
+		switch (option) {
+		case 'e':
+			parse_endian (optarg, &from, &to);
+			break;
+		default:
+			return usage ();
 		}
-
-		prindent (indent);
-		printf ("} %s", name);
-		break;
-	case T_UNION:
-		printf ("union {\n");
-
-		for (struct uitem **i = ty->un; *i != NULL; ++i) {
-			struct uitem *ui = *i;
-			prindent (indent + 1);
-			print_item2 (ui->type, ui->name, indent + 1);
-			printf (" // if ");
-			print_cond (ui->cond, "");
-			puts (";");
-		}
-
-		prindent (indent);
-		printf ("} %s", name);
-		break;
 	}
-}
+	
+	argv += optind;
+	argc -= optind;
 
-void print_item (struct item *it)
-{
-	putchar ('\t');
-	print_item2 (it->type, it->name, 1);
-	puts (";");
-}
-
-void print_structure (struct structure *st)
-{
-	if (st->name == NULL)
-		errx (1, "a top-level structure was declared without a name");
-
-	printf ("struct %s {\n", st->name);
-	for (struct item **it = st->items; *it != NULL; ++it) {
-		print_item (*it);
+	if (argc == 1) {
+		if (freopen (argv[0], "r", stdin) == NULL)
+			err (1, "cannot open '%s'", argv[0]);
+	} else if (argc > 1) {
+		return usage ();
 	}
-	puts ("};\n");
-}
 
-void encode (size_t *offset, struct type *ty, const char *from, const char *parent, int indent)
-{
-	size_t sz, off2;
-	char *s;
-
-	*offset = align (*offset, align_of (ty));
-	sz = size_of (ty);
-
-	switch (ty->type) {
-	case T_I8:
-	case T_I16:
-	case T_I32:
-	case T_I64:
-	case T_U8:
-	case T_U16:
-	case T_U32:
-	case T_U64:
-		prindent (indent);
-		printf ("write%zu (out + %zu, %s);\n", sz * 8, *offset, from);
-		*offset += sz;
-		break;
-	case T_ARRAY:
-		for (size_t i = 0; i < ty->len; ++i) {
-			asprintf (&s, "%s[%zu]", from, i);
-			encode (offset, ty->inner, s, parent, indent);
-			free (s);
-		}
-		break;
-	case T_NAME:
-		prindent (indent);
-		printf ("encode_%s (out + %zu, &%s);\n", ty->name, *offset, from);
-		*offset += sz;
-		break;
-	case T_STRUCT:
-		for (struct item **i = ty->st->items; *i != NULL; ++i) {
-			struct item *it = *i;
-			asprintf (&s, "%s.%s", from, it->name);
-			encode (offset, it->type, s, from, indent);
-			free (s);
-		}
-		break;
-	case T_UNION:
-		prindent (indent);
-		for (struct uitem **i = ty->un; *i != NULL; ++i) {
-			struct uitem *ui = *i;
-			char *prefix;
-
-			asprintf (&prefix, "%s.", parent);
-			printf ("if (");
-			print_cond (ui->cond, prefix);
-			printf (") {\n");
-			free (prefix);
-
-			off2 = *offset;
-			asprintf (&s, "%s.%s", from, ui->name);
-			encode (&off2, ui->type, s, parent, indent + 1);
-			free (s);
-			prindent (indent);
-			printf ("} else ");
-		}
-		puts (";");
-		*offset += size_of_union (ty->un);
-		break;
-	}
-}
-
-void print_encode (struct structure *st)
-{
-	printf ("static void encode_%s (uint8_t *out, const struct %s *in)\n", st->name, st->name);
-	puts ("{");
-
-	size_t offset = 0;
-
-	for (struct item **i = st->items; *i != NULL; ++i) {
-		struct item *it = *i;
-		char *from;
-
-		asprintf (&from, "in->%s", it->name);
-		encode (&offset, it->type, from, "(*in)", 1);
-		free (from);
-	}
-
-	puts ("}\n");
-}
-
-void decode (size_t *offset, struct type *ty, const char *into, const char *parent, int indent)
-{
-	size_t sz, off2;
-	char *s;
-
-	*offset = align (*offset, align_of (ty));
-	sz = size_of (ty);
-
-	switch (ty->type) {
-	case T_I8:
-	case T_I16:
-	case T_I32:
-	case T_I64:
-	case T_U8:
-	case T_U16:
-	case T_U32:
-	case T_U64:
-		prindent (indent);
-		printf ("%s = read%zu (in + %zu);\n", into, sz * 8, *offset);
-		*offset += sz;
-		break;
-	case T_ARRAY:
-		for (size_t i = 0; i < ty->len; ++i) {
-			asprintf (&s, "%s[%zu]", into, i);
-			decode (offset, ty->inner, s, parent, indent);
-			free (s);
-		}
-		break;
-	case T_NAME:
-		prindent (indent);
-		printf ("decode_%s (&%s, in + %zu);\n", ty->name, into, *offset);
-		*offset += sz;
-		break;
-	case T_STRUCT:
-		for (struct item **i = ty->st->items; *i != NULL; ++i) {
-			struct item *it = *i;
-			asprintf (&s, "%s.%s", into, it->name);
-			decode (offset, it->type, s, into, indent);
-			free (s);
-		}
-		break;
-	case T_UNION:
-		prindent (indent);
-		for (struct uitem **i = ty->un; *i != NULL; ++i) {
-			struct uitem *ui = *i;
-			char *prefix;
-
-			asprintf (&prefix, "%s.", parent);
-			printf ("if (");
-			print_cond (ui->cond, prefix);
-			printf (") {\n");
-			free (prefix);
-
-			off2 = *offset;
-			asprintf (&s, "%s.%s", into, ui->name);
-			decode (&off2, ui->type, s, parent, indent + 1);
-			free (s);
-			prindent (indent);
-			printf ("} else ");
-		}
-		puts (";");
-		*offset += size_of_union (ty->un);
-		break;
-	}
-}
-
-void print_decode (struct structure *st)
-{
-	printf ("static void decode_%s (struct %s *out, uint8_t *in)\n", st->name, st->name);
-	puts ("{");
-
-	size_t offset = 0;
-
-	for (struct item **i = st->items; *i != NULL; ++i) {
-		struct item *it = *i;
-		size_t sz = size_of (it->type);
-		char *into;
-
-		asprintf (&into, "out->%s", it->name);
-		decode (&offset, it->type, into, "(*out)", 1);
-		free (into);
-	}
-
-	puts ("}\n");
-}
-
-static const char *header =
-#include "destruct.inc"
-;
-
-int main (void)
-{
 	file = parse ();
 
 	if (file == NULL) {
@@ -421,18 +77,7 @@ int main (void)
 		return 1;
 	}
 
-	puts (header);
+	gen (file, from, to);
 
-	// Declare the structures
-	for (struct structure **st = file; *st != NULL; ++st) {
-		print_structure (*st);
-	}
-
-	// Define functions
-	for (struct structure **st = file; *st != NULL; ++st) {
-		print_encode (*st);
-		print_decode (*st);
-	}
-
 	return 0;
 }
blob - /dev/null
blob + d8784b15cf600d97e8da34aee1185723093aecf9 (mode 644)
--- /dev/null
+++ gen.c
@@ -0,0 +1,438 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include "ast.h"
+
+static struct structure **file;
+
+struct structure *get_struct (const char *name)
+{
+	for (struct structure **i = file; *i != NULL; ++i) {
+		struct structure *st = *i;
+		if (strcmp (name, st->name) == 0)
+			return st;
+	}
+	errx (1, "invalid struct: %s", name);
+}
+
+size_t size_of_struct (struct structure *st);
+size_t size_of_union (struct uitem **u);
+size_t size_of (struct type *ty)
+{
+	switch (ty->type) {
+	case T_I8:
+	case T_U8:
+		return 1;
+	case T_I16:
+	case T_U16:
+		return 2;
+	case T_I32:
+	case T_U32:
+		return 4;
+	case T_I64:
+	case T_U64:
+		return 8;
+	case T_ARRAY:
+		return ty->len * size_of (ty->inner);
+	case T_NAME:
+		return size_of_struct (get_struct (ty->name));
+	case T_STRUCT:
+		return size_of_struct (ty->st);
+	case T_UNION:
+		return size_of_union (ty->un);
+	}
+}
+
+size_t size_of_struct (struct structure *st)
+{
+	size_t sz = 0;
+
+	for (struct item **i = st->items; *i != NULL; ++i) {
+		sz += size_of ((*i)->type);
+	}
+
+	return sz;
+}
+
+size_t size_of_union (struct uitem **u)
+{
+	size_t sz = 0;
+
+	for (struct uitem **i = u; *i != NULL; ++i) {
+		size_t s = size_of ((*i)->type);
+		if (s > sz)
+			sz = s;
+	}
+
+	return sz;
+}
+
+size_t align_of_struct (struct structure *st);
+size_t align_of_union (struct uitem **u);
+size_t align_of (struct type *ty)
+{
+	switch (ty->type) {
+	case T_I8:
+	case T_U8:
+	case T_I16:
+	case T_U16:
+	case T_I32:
+	case T_U32:
+	case T_I64:
+	case T_U64:
+		return size_of (ty);
+	case T_ARRAY:
+		return align_of (ty->inner);
+	case T_NAME:
+		return align_of_struct (get_struct (ty->name));
+	case T_STRUCT:
+		return align_of_struct (ty->st);
+	case T_UNION:
+		return align_of_union (ty->un);
+	}
+}
+
+size_t align_of_struct (struct structure *st)
+{
+	size_t al = 0;
+
+	for (struct item **i = st->items; *i != NULL; ++i) {
+		size_t a = align_of ((*i)->type);
+		if (a > al)
+			al = a;
+	}
+
+	return al;
+}
+
+size_t align_of_union (struct uitem **u)
+{
+	size_t al = 0;
+
+	for (struct uitem **i = u; *i != NULL; ++i) {
+		size_t a = align_of ((*i)->type);
+		if (a > al)
+			al = a;
+	}
+
+	return al;
+}
+
+size_t align (size_t offset, size_t alignment)
+{
+	return (offset + alignment - 1) & -alignment;
+}
+
+void prindent (int ind)
+{
+	for (int i = 0; i < ind; ++i)
+		putchar ('\t');
+}
+
+void print_value (struct value *v)
+{
+	switch (v->type) {
+	case V_NAME:
+		printf ("%s", v->s);
+		break;
+	case V_INT:
+		printf ("%d", v->i);
+		break;
+	}
+}
+
+void print_cond (struct cond *co, const char *prefix)
+{
+	switch (co->type) {
+	case C_EQ:
+		printf ("%s%s == ", prefix, co->cmp.left);
+		print_value (co->cmp.right);
+		break;
+	}
+}
+
+void print_item2 (struct type *ty, const char *name, int indent)
+{
+	switch (ty->type) {
+	case T_I8:
+		printf ("int8_t %s", name);
+		break;
+	case T_I16:
+		printf ("int16_t %s", name);
+		break;
+	case T_I32:
+		printf ("int32_t %s", name);
+		break;
+	case T_I64:
+		printf ("int64_t %s", name);
+		break;
+	case T_U8:
+		printf ("uint8_t %s", name);
+		break;
+	case T_U16:
+		printf ("uint16_t %s", name);
+		break;
+	case T_U32:
+		printf ("uint32_t %s", name);
+		break;
+	case T_U64:
+		printf ("uint64_t %s", name);
+		break;
+	case T_ARRAY:
+		print_item2 (ty->inner, name, indent);
+		printf ("[%zu]", ty->len);
+		break;
+	case T_NAME:
+		printf ("struct %s %s", ty->name, name);
+		break;
+	case T_STRUCT:
+		printf ("struct {\n");
+
+		for (struct item **i = ty->st->items; *i != NULL; ++i) {
+			struct item *it = *i;
+			prindent (indent + 1);
+			print_item2 (it->type, it->name, indent + 1);
+			puts (";");
+		}
+
+		prindent (indent);
+		printf ("} %s", name);
+		break;
+	case T_UNION:
+		printf ("union {\n");
+
+		for (struct uitem **i = ty->un; *i != NULL; ++i) {
+			struct uitem *ui = *i;
+			prindent (indent + 1);
+			print_item2 (ui->type, ui->name, indent + 1);
+			printf (" // if ");
+			print_cond (ui->cond, "");
+			puts (";");
+		}
+
+		prindent (indent);
+		printf ("} %s", name);
+		break;
+	}
+}
+
+void print_item (struct item *it)
+{
+	putchar ('\t');
+	print_item2 (it->type, it->name, 1);
+	puts (";");
+}
+
+void print_structure (struct structure *st)
+{
+	if (st->name == NULL)
+		errx (1, "a top-level structure was declared without a name");
+
+	printf ("struct %s {\n", st->name);
+	for (struct item **it = st->items; *it != NULL; ++it) {
+		print_item (*it);
+	}
+	puts ("};\n");
+}
+
+void encode (size_t *offset, struct type *ty, const char *from, const char *parent, int indent)
+{
+	size_t sz, off2;
+	char *s;
+
+	*offset = align (*offset, align_of (ty));
+	sz = size_of (ty);
+
+	switch (ty->type) {
+	case T_I8:
+	case T_I16:
+	case T_I32:
+	case T_I64:
+	case T_U8:
+	case T_U16:
+	case T_U32:
+	case T_U64:
+		prindent (indent);
+		printf ("write%zu (out + %zu, %s);\n", sz * 8, *offset, from);
+		*offset += sz;
+		break;
+	case T_ARRAY:
+		for (size_t i = 0; i < ty->len; ++i) {
+			asprintf (&s, "%s[%zu]", from, i);
+			encode (offset, ty->inner, s, parent, indent);
+			free (s);
+		}
+		break;
+	case T_NAME:
+		prindent (indent);
+		printf ("encode_%s (out + %zu, &%s);\n", ty->name, *offset, from);
+		*offset += sz;
+		break;
+	case T_STRUCT:
+		for (struct item **i = ty->st->items; *i != NULL; ++i) {
+			struct item *it = *i;
+			asprintf (&s, "%s.%s", from, it->name);
+			encode (offset, it->type, s, from, indent);
+			free (s);
+		}
+		break;
+	case T_UNION:
+		prindent (indent);
+		for (struct uitem **i = ty->un; *i != NULL; ++i) {
+			struct uitem *ui = *i;
+			char *prefix;
+
+			asprintf (&prefix, "%s.", parent);
+			printf ("if (");
+			print_cond (ui->cond, prefix);
+			printf (") {\n");
+			free (prefix);
+
+			off2 = *offset;
+			asprintf (&s, "%s.%s", from, ui->name);
+			encode (&off2, ui->type, s, parent, indent + 1);
+			free (s);
+			prindent (indent);
+			printf ("} else ");
+		}
+		puts (";");
+		*offset += size_of_union (ty->un);
+		break;
+	}
+}
+
+void print_encode (struct structure *st)
+{
+	printf ("static void encode_%s (uint8_t *out, const struct %s *in)\n", st->name, st->name);
+	puts ("{");
+
+	size_t offset = 0;
+
+	for (struct item **i = st->items; *i != NULL; ++i) {
+		struct item *it = *i;
+		char *from;
+
+		asprintf (&from, "in->%s", it->name);
+		encode (&offset, it->type, from, "(*in)", 1);
+		free (from);
+	}
+
+	puts ("}\n");
+}
+
+void decode (size_t *offset, struct type *ty, const char *into, const char *parent, int indent)
+{
+	size_t sz, off2;
+	char *s;
+
+	*offset = align (*offset, align_of (ty));
+	sz = size_of (ty);
+
+	switch (ty->type) {
+	case T_I8:
+	case T_I16:
+	case T_I32:
+	case T_I64:
+	case T_U8:
+	case T_U16:
+	case T_U32:
+	case T_U64:
+		prindent (indent);
+		printf ("%s = read%zu (in + %zu);\n", into, sz * 8, *offset);
+		*offset += sz;
+		break;
+	case T_ARRAY:
+		for (size_t i = 0; i < ty->len; ++i) {
+			asprintf (&s, "%s[%zu]", into, i);
+			decode (offset, ty->inner, s, parent, indent);
+			free (s);
+		}
+		break;
+	case T_NAME:
+		prindent (indent);
+		printf ("decode_%s (&%s, in + %zu);\n", ty->name, into, *offset);
+		*offset += sz;
+		break;
+	case T_STRUCT:
+		for (struct item **i = ty->st->items; *i != NULL; ++i) {
+			struct item *it = *i;
+			asprintf (&s, "%s.%s", into, it->name);
+			decode (offset, it->type, s, into, indent);
+			free (s);
+		}
+		break;
+	case T_UNION:
+		prindent (indent);
+		for (struct uitem **i = ty->un; *i != NULL; ++i) {
+			struct uitem *ui = *i;
+			char *prefix;
+
+			asprintf (&prefix, "%s.", parent);
+			printf ("if (");
+			print_cond (ui->cond, prefix);
+			printf (") {\n");
+			free (prefix);
+
+			off2 = *offset;
+			asprintf (&s, "%s.%s", into, ui->name);
+			decode (&off2, ui->type, s, parent, indent + 1);
+			free (s);
+			prindent (indent);
+			printf ("} else ");
+		}
+		puts (";");
+		*offset += size_of_union (ty->un);
+		break;
+	}
+}
+
+void print_decode (struct structure *st)
+{
+	printf ("static void decode_%s (struct %s *out, uint8_t *in)\n", st->name, st->name);
+	puts ("{");
+
+	size_t offset = 0;
+
+	for (struct item **i = st->items; *i != NULL; ++i) {
+		struct item *it = *i;
+		size_t sz = size_of (it->type);
+		char *into;
+
+		asprintf (&into, "out->%s", it->name);
+		decode (&offset, it->type, into, "(*out)", 1);
+		free (into);
+	}
+
+	puts ("}\n");
+}
+
+static const char *header =
+#include "destruct.inc"
+;
+
+void gen (struct structure **f, int from, int to)
+{
+	file = f;
+
+	puts ("#ifndef DST_FROM_ENDIAN");
+	printf ("# define DST_FROM_ENDIAN %d\n", from);
+	puts ("#endif\n");
+
+	puts ("#ifndef DST_TO_ENDIAN");
+	printf ("# define DST_TO_ENDIAN %d\n", to);
+	puts ("#endif\n");
+
+	puts (header);
+
+	// Declare the structures
+	for (struct structure **st = file; *st != NULL; ++st) {
+		print_structure (*st);
+	}
+
+	// Define functions
+	for (struct structure **st = file; *st != NULL; ++st) {
+		print_encode (*st);
+		print_decode (*st);
+	}
+}