commit 9be3f8306dc92152ec1af230d2a54cbf3415a976 from: Benjamin Stürz date: Fri Jul 05 11:16:12 2024 UTC implement creationg of header files commit - ec716a83243eeb924f17d2d31a4401c98681c673 commit + 9be3f8306dc92152ec1af230d2a54cbf3415a976 blob - 3ee1a951bf1c57a144bb0c4d42ad311a08dc983b blob + b01f1c55cb4f2b49ac28a0eef40040777fc3d561 --- .gitignore +++ .gitignore @@ -1,6 +1,7 @@ destruct destruct.inc y.tab.h +test.[ch] *.o *.swp *.core blob - b4fe389695079fcfcfca811492f94f2ea77ed2dc blob + 593c0f5e809e181c9ee6f36b3e883793c144170f --- Makefile +++ Makefile @@ -3,10 +3,11 @@ OBJ = parse.o lex.o gen.o main.o 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 @@ -1,5 +1,6 @@ #ifndef FILE_AST_H #define FILE_AST_H +#include enum type_type { T_I8, @@ -72,4 +73,7 @@ struct uitem { 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 @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "ast.h" @@ -124,119 +125,119 @@ size_t align (size_t offset, size_t alignment) 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; @@ -253,59 +254,58 @@ void encode (size_t *offset, struct type *ty, const ch 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; @@ -314,14 +314,14 @@ void print_encode (struct structure *st) 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; @@ -338,59 +338,58 @@ void decode (size_t *offset, struct type *ty, const ch 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; @@ -400,39 +399,89 @@ void print_decode (struct structure *st) 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 \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 @@ -8,9 +8,6 @@ #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) { @@ -40,21 +37,29 @@ void parse_endian (char *s, int *from, int *to) 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 (); } @@ -70,6 +75,18 @@ int main (int argc, char *argv[]) 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) { @@ -77,7 +94,7 @@ int main (int argc, char *argv[]) return 1; } - gen (file, from, to); + gen (file, hdrpath, hdr, src, from, to); return 0; } blob - 0765b0168719e313ce4f1f1df97423ee10cb54cb blob + 03a1ee5bbe7953382aa7c52d8d258a0d0c5df460 --- test.txt +++ test.txt @@ -19,7 +19,24 @@ struct asdf { }, 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, +};