diff options
Diffstat (limited to 'bie.c')
-rw-r--r-- | bie.c | 134 |
1 files changed, 134 insertions, 0 deletions
@@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> + * SPDX-License-Identifier: MIT + */ +#include <ctype.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include "eprintf.h" + +#ifndef VERSION +#define VERSION "v0.1" +#endif + +enum { + ALIGN = 16, +}; + +static const char *usage = "[-hv] [--] output map input..."; + +static void help(void) +{ + fprintf(stderr, + "Options:\n" + " -h Show this help.\n" + " -v Show version and license information.\n" + "\n" + "Please check the bie(1) man page for more information.\n"); +} + +static void version(void) +{ + fprintf(stderr, + "bie %s\n" + "Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>\n" + "Licensed under the MIT license <https://opensource.org/licenses/MIT>\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + VERSION); +} + +static void slug(FILE *f, const char *text) +{ + bool leading = true; + int c; + + while (c = *text++, c != '\0') { + if (isalpha(c)) { + leading = false; + fputc(c, f); + continue; + } + if (leading) continue; + if (isdigit(c)) + fputc(c, f); + else if (ispunct(c) || isspace(c)) + fputc('_', f); + } +} + +static void mapentry(FILE *map, const char *name, size_t pos, size_t size) +{ + fprintf(map, "BIE_ENTRY("); + slug(map, name); + fprintf(map, ", %zu, %zu)\n", pos, size); +} + +static size_t dumpfile(FILE *dest, FILE *src) +{ + size_t size = 0; + int c; + + while (c = fgetc(src), c != EOF) { + size++; + fputc(c, dest); + } + + return size; +} + +int main(int argc, char **argv) +{ + const char *argv0 = argv[0] != NULL ? argv[0] : "bie"; + FILE *dest, *map; + size_t pos = 0; + + setprogname(argv0); + + for (argv++, argc--; argv[0] != NULL && argv[0][0] == '-' && + argv[0][1] != '-' && argv[0][2] == '\0'; argv++, argc--) { + switch (argv[0][1]) { + case 'h': + fprintf(stderr, "Usage: %s %s\n", argv0, usage); + help(); + return EXIT_SUCCESS; + case 'v': + version(); + return EXIT_SUCCESS; + } + } + + if (argc < 3) + eprintf("Invalid argument count\nUsage: %s %s", argv0, usage); + + dest = fopen(argv[0], "wb"); + if (dest == NULL) + eprintf("Could not open `%s':", argv[0]); + + map = fopen(argv[1], "w"); + if (map == NULL) + eprintf("Could not open `%s':", argv[1]); + + for (int i = 2; i < argc; i++) { + size_t size; + FILE *src; + + src = fopen(argv[i], "rb"); + if (src == NULL) + eprintf("Could not open `%s':", argv[i]); + size = dumpfile(dest, src); + fclose(src); + mapentry(map, argv[i], pos, size); + pos += size; + if (pos % ALIGN) { + size_t pad = ALIGN - pos % ALIGN; + for (size_t i = 0; i < pad; i++) + fputc(0, dest); + pos += pad; + } + } + + fclose(map); + fclose(dest); +} |