commit ec716a83243eeb924f17d2d31a4401c98681c673 from: Benjamin Stürz date: Fri Jul 05 09:13:27 2024 UTC add a CLI 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 #include -#include #include #include #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 +#include +#include +#include +#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); + } +}