commit - 780459fb4692655b2d9c001d8f0f992c21c9bf46
commit + ec716a83243eeb924f17d2d31a4401c98681c673
blob - fa63cc7bf930d8d95f48b8331ce6579de841d6f9
blob + b4fe389695079fcfcfca811492f94f2ea77ed2dc
--- Makefile
+++ Makefile
-OBJ = parse.o lex.o main.o
+OBJ = parse.o lex.o gen.o main.o
all: 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
+destruct
+destruct.inc
+y.tab.h
+*.o
+*.swp
+*.core
blob - 21b050e2a21535b5b02681de5aa6b48b6305eb1b
blob + e9b7907d4c124ac1ac36ca3bea04d40efa4bdebb
--- main.c
+++ main.c
+#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) {
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
+#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);
+ }
+}