commit - ec716a83243eeb924f17d2d31a4401c98681c673
commit + 9be3f8306dc92152ec1af230d2a54cbf3415a976
blob - 3ee1a951bf1c57a144bb0c4d42ad311a08dc983b
blob + b01f1c55cb4f2b49ac28a0eef40040777fc3d561
--- .gitignore
+++ .gitignore
destruct
destruct.inc
y.tab.h
+test.[ch]
*.o
*.swp
*.core
blob - b4fe389695079fcfcfca811492f94f2ea77ed2dc
blob + 593c0f5e809e181c9ee6f36b3e883793c144170f
--- Makefile
+++ Makefile
all: destruct
run: destruct
- ./destruct < test.txt
+ ./destruct -H test.h -o test.c test.txt
+ cat test.h test.c
clean:
- rm -f destruct destruct.inc y.tab.h *.o *.core
+ rm -f destruct destruct.inc y.tab.h test.[ch] *.o *.core
destruct: destruct.inc ${OBJ}
${CC} -o $@ ${OBJ}
blob - 339db3a7c4e04375fbde0643a28935bcecba749d
blob + 4b45bdda08790cc04f7060be072644d7a09cd74c
--- ast.h
+++ ast.h
#ifndef FILE_AST_H
#define FILE_AST_H
+#include <stdio.h>
enum type_type {
T_I8,
struct cond *cond;
};
+void gen (struct structure **, const char *hdrpath, FILE *hdr, FILE *src, int from, int to);
+struct structure **parse (void);
+
#endif // FILE_AST_H
blob - d8784b15cf600d97e8da34aee1185723093aecf9
blob + f91f8a2a73220dc687f44ec3b53363be1801755e
--- gen.c
+++ gen.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <err.h>
#include "ast.h"
return (offset + alignment - 1) & -alignment;
}
-void prindent (int ind)
+void prindent (FILE *out, int ind)
{
for (int i = 0; i < ind; ++i)
- putchar ('\t');
+ fputc ('\t', out);
}
-void print_value (struct value *v)
+void print_value (FILE *out, struct value *v)
{
switch (v->type) {
case V_NAME:
- printf ("%s", v->s);
+ fprintf (out, "%s", v->s);
break;
case V_INT:
- printf ("%d", v->i);
+ fprintf (out, "%d", v->i);
break;
}
}
-void print_cond (struct cond *co, const char *prefix)
+void print_cond (FILE *out, struct cond *co, const char *prefix)
{
switch (co->type) {
case C_EQ:
- printf ("%s%s == ", prefix, co->cmp.left);
- print_value (co->cmp.right);
+ fprintf (out, "%s%s == ", prefix, co->cmp.left);
+ print_value (out, co->cmp.right);
break;
}
}
-void print_item2 (struct type *ty, const char *name, int indent)
+void print_item2 (FILE *out, struct type *ty, const char *name, int indent)
{
switch (ty->type) {
case T_I8:
- printf ("int8_t %s", name);
+ fprintf (out, "int8_t %s", name);
break;
case T_I16:
- printf ("int16_t %s", name);
+ fprintf (out, "int16_t %s", name);
break;
case T_I32:
- printf ("int32_t %s", name);
+ fprintf (out, "int32_t %s", name);
break;
case T_I64:
- printf ("int64_t %s", name);
+ fprintf (out, "int64_t %s", name);
break;
case T_U8:
- printf ("uint8_t %s", name);
+ fprintf (out, "uint8_t %s", name);
break;
case T_U16:
- printf ("uint16_t %s", name);
+ fprintf (out, "uint16_t %s", name);
break;
case T_U32:
- printf ("uint32_t %s", name);
+ fprintf (out, "uint32_t %s", name);
break;
case T_U64:
- printf ("uint64_t %s", name);
+ fprintf (out, "uint64_t %s", name);
break;
case T_ARRAY:
- print_item2 (ty->inner, name, indent);
- printf ("[%zu]", ty->len);
+ print_item2 (out, ty->inner, name, indent);
+ fprintf (out, "[%zu]", ty->len);
break;
case T_NAME:
- printf ("struct %s %s", ty->name, name);
+ fprintf (out, "struct %s %s", ty->name, name);
break;
case T_STRUCT:
- printf ("struct {\n");
+ fprintf (out, "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 (out, indent + 1);
+ print_item2 (out, it->type, it->name, indent + 1);
+ fputs (";\n", out);
}
- prindent (indent);
- printf ("} %s", name);
+ prindent (out, indent);
+ fprintf (out, "} %s", name);
break;
case T_UNION:
- printf ("union {\n");
+ fputs ("union {\n", out);
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 (out, indent + 1);
+ print_item2 (out, ui->type, ui->name, indent + 1);
+ fprintf (out, "; // if ");
+ print_cond (out, ui->cond, "");
+ fputc ('\n', out);
}
- prindent (indent);
- printf ("} %s", name);
+ prindent (out, indent);
+ fprintf (out, "} %s", name);
break;
}
}
-void print_item (struct item *it)
+void print_item (FILE *out, struct item *it)
{
- putchar ('\t');
- print_item2 (it->type, it->name, 1);
- puts (";");
+ fputc ('\t', out);
+ print_item2 (out, it->type, it->name, 1);
+ fputs (";\n", out);
}
-void print_structure (struct structure *st)
+void print_structure (FILE *out, struct structure *st)
{
if (st->name == NULL)
errx (1, "a top-level structure was declared without a name");
- printf ("struct %s {\n", st->name);
+ fprintf (out, "struct %s {\n", st->name);
for (struct item **it = st->items; *it != NULL; ++it) {
- print_item (*it);
+ print_item (out, *it);
}
- puts ("};\n");
+ fputs ("};\n\n", out);
}
-void encode (size_t *offset, struct type *ty, const char *from, const char *parent, int indent)
+void encode (FILE *out, size_t *offset, struct type *ty, const char *from, const char *parent, int indent)
{
size_t sz, off2;
char *s;
case T_U16:
case T_U32:
case T_U64:
- prindent (indent);
- printf ("write%zu (out + %zu, %s);\n", sz * 8, *offset, from);
+ prindent (out, indent);
+ fprintf (out, "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);
+ encode (out, 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);
+ prindent (out, indent);
+ fprintf (out, "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);
+ encode (out, offset, it->type, s, from, indent);
free (s);
}
break;
case T_UNION:
- prindent (indent);
+ prindent (out, 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");
+ fputs ("if (", out);
+ print_cond (out, ui->cond, prefix);
+ fputs (") {\n", out);
free (prefix);
off2 = *offset;
asprintf (&s, "%s.%s", from, ui->name);
- encode (&off2, ui->type, s, parent, indent + 1);
+ encode (out, &off2, ui->type, s, parent, indent + 1);
free (s);
- prindent (indent);
- printf ("} else ");
+ prindent (out, indent);
+ fputs ("} else ", out);
}
- puts (";");
+ fputs (";\n", out);
*offset += size_of_union (ty->un);
break;
}
}
-void print_encode (struct structure *st)
+void print_encode (FILE *out, struct structure *st)
{
- printf ("static void encode_%s (uint8_t *out, const struct %s *in)\n", st->name, st->name);
- puts ("{");
+ fprintf (out, "static void encode_%s (uint8_t *out, const struct %s *in)\n{\n", st->name, st->name);
size_t offset = 0;
char *from;
asprintf (&from, "in->%s", it->name);
- encode (&offset, it->type, from, "(*in)", 1);
+ encode (out, &offset, it->type, from, "(*in)", 1);
free (from);
}
- puts ("}\n");
+ fputs ("}\n\n", out);
}
-void decode (size_t *offset, struct type *ty, const char *into, const char *parent, int indent)
+void decode (FILE *out, size_t *offset, struct type *ty, const char *into, const char *parent, int indent)
{
size_t sz, off2;
char *s;
case T_U16:
case T_U32:
case T_U64:
- prindent (indent);
- printf ("%s = read%zu (in + %zu);\n", into, sz * 8, *offset);
+ prindent (out, indent);
+ fprintf (out, "%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);
+ decode (out, 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);
+ prindent (out, indent);
+ fprintf (out, "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);
+ decode (out, offset, it->type, s, into, indent);
free (s);
}
break;
case T_UNION:
- prindent (indent);
+ prindent (out, 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");
+ fputs ("if (", out);
+ print_cond (out, ui->cond, prefix);
+ fputs (") {\n", out);
free (prefix);
off2 = *offset;
asprintf (&s, "%s.%s", into, ui->name);
- decode (&off2, ui->type, s, parent, indent + 1);
+ decode (out, &off2, ui->type, s, parent, indent + 1);
free (s);
- prindent (indent);
- printf ("} else ");
+ prindent (out, indent);
+ fputs ("} else ", out);
}
- puts (";");
+ fputs (";\n", out);
*offset += size_of_union (ty->un);
break;
}
}
-void print_decode (struct structure *st)
+void print_decode (FILE *out, struct structure *st)
{
- printf ("static void decode_%s (struct %s *out, uint8_t *in)\n", st->name, st->name);
- puts ("{");
+ fprintf (out, "static void decode_%s (struct %s *out, uint8_t *in)\n{\n", st->name, st->name);
size_t offset = 0;
char *into;
asprintf (&into, "out->%s", it->name);
- decode (&offset, it->type, into, "(*out)", 1);
+ decode (out, &offset, it->type, into, "(*out)", 1);
free (into);
}
- puts ("}\n");
+ fputs ("}\n\n", out);
}
+void declare (FILE *out, struct structure *st)
+{
+ fprintf (out, "static void encode_%s (uint8_t *out, const struct %s *in);\n", st->name, st->name);
+ fprintf (out, "static void decode_%s (struct %s *out, uint8_t *in);\n", st->name, st->name);
+}
+
static const char *header =
#include "destruct.inc"
;
-void gen (struct structure **f, int from, int to)
+void include_guard (char *path)
{
+ char *s;
+
+ s = strrchr (s, '/');
+ if (s != NULL) {
+ ++s;
+ } else {
+ s = path;
+ }
+
+ for (; *s != '\0'; ++s) {
+ switch (*s) {
+ case '.':
+ case '/':
+ *s = '_';
+ break;
+ default:
+ *s = toupper (*s);
+ break;
+ }
+ }
+}
+
+void gen (struct structure **f, const char *hdrpath, FILE *hdr, FILE *src, int from, int to)
+{
+ char *inc = NULL;
+
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");
+ if (hdrpath != NULL) {
+ fprintf (src, "#include \"%s\"\n\n", hdrpath);
+ inc = strdup (hdrpath);
+ include_guard (inc);
+ fprintf (hdr, "#ifndef FILE_%s\n", inc);
+ fprintf (hdr, "#define FILE_%s\n", inc);
+ }
- puts (header);
+ fputs ("#include <stdint.h>\n\n", hdr);
+ fprintf (src, "#ifndef DST_FROM_ENDIAN\n");
+ fprintf (src, "# define DST_FROM_ENDIAN %d\n", from);
+ fprintf (src, "#endif\n\n");
+
+ fprintf (src, "#ifndef DST_TO_ENDIAN\n");
+ fprintf (src, "# define DST_TO_ENDIAN %d\n", to);
+ fprintf (src, "#endif\n\n");
+
+ fputs (header, src);
+ fputc ('\n', src);
+
+
// Declare the structures
for (struct structure **st = file; *st != NULL; ++st) {
- print_structure (*st);
+ print_structure (hdr, *st);
}
// Define functions
- for (struct structure **st = file; *st != NULL; ++st) {
- print_encode (*st);
- print_decode (*st);
+ for (struct structure **i = file; *i != NULL; ++i) {
+ struct structure *st = *i;
+ declare (hdr, st);
+ print_encode (src, st);
+ print_decode (src, st);
}
+
+ if (inc != NULL)
+ fprintf (hdr, "\n#endif // FILE_%s\n", inc);
}
blob - e9b7907d4c124ac1ac36ca3bea04d40efa4bdebb
blob + 9c8bd4d25f744c526e3fecc3586cc3c3cadaf8c0
--- main.c
+++ main.c
#define DST_BIG_ENDIAN 4321
#define DST_DEFAULT_ENDIAN DST_LITTLE_ENDIAN
-void gen (struct structure **, int from, int to);
-struct structure **parse (void);
-
int parse_endian2 (const char *s)
{
if (strcmp (s, "little") == 0) {
int usage (void)
{
- fputs ("usage: destruct [-e endian[:endian]]\n", stderr);
+ fputs ("usage: destruct [-e endian[:endian]] [-H headerfile] [-o srcfile] [input]\n", stderr);
return 1;
}
int main (int argc, char *argv[])
{
struct structure **file;
+ const char *hdrpath = NULL, *srcpath = NULL;
+ FILE *src = stdout, *hdr = stdout;
int from = DST_DEFAULT_ENDIAN, to = DST_DEFAULT_ENDIAN;
int option;
- while ((option = getopt (argc, argv, "e:")) != -1) {
+ while ((option = getopt (argc, argv, "e:H:o:")) != -1) {
switch (option) {
case 'e':
parse_endian (optarg, &from, &to);
break;
+ case 'H':
+ hdrpath = optarg;
+ break;
+ case 'o':
+ srcpath = optarg;
+ break;
default:
return usage ();
}
return usage ();
}
+ if (hdrpath != NULL) {
+ hdr = fopen (hdrpath, "w");
+ if (hdr == NULL)
+ err (1, "cannot open '%s'", hdrpath);
+ }
+
+ if (srcpath != NULL) {
+ src = fopen (srcpath, "w");
+ if (src == NULL)
+ err (1, "cannot open '%s'", srcpath);
+ }
+
file = parse ();
if (file == NULL) {
return 1;
}
- gen (file, from, to);
+ gen (file, hdrpath, hdr, src, from, to);
return 0;
}
blob - 0765b0168719e313ce4f1f1df97423ee10cb54cb
blob + 03a1ee5bbe7953382aa7c52d8d258a0d0c5df460
--- test.txt
+++ test.txt
},
u: union {
a: u8 if x == 0,
- b: u8 if x == 0,
+ b: u8 if x == 1,
},
z: i8,
};
+
+struct elf64_ehdr {
+ ident: [u8; 16],
+ type: u16,
+ machine: u16,
+ version: u32,
+ entry: u64,
+ phoff: u64,
+ shoff: u64,
+ flags: u32,
+ ehsize: u16,
+ phentsize: u16,
+ phnum: u16,
+ shentsize: u16,
+ shnum: u16,
+ shstrndx: u16,
+};