Mercurial > sci
diff extern/bcc/bcc.c @ 0:f1de39079243
misc: initial import
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 07 Jun 2021 09:41:37 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extern/bcc/bcc.c Mon Jun 07 09:41:37 2021 +0200 @@ -0,0 +1,164 @@ +/* + * bcc.c -- binary to C/C++ arrays converter + * + * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdnoreturn.h> +#include <string.h> +#include <unistd.h> + +static const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; +static char findentchar = '\t'; +static int findent = 1, fconst, fnull, fstatic; + +noreturn static void +usage(void) +{ + fprintf(stderr, "usage: bcc [-0cs] [-I tab-indent] [-i space-indent] input variable\n"); + exit(1); +} + +noreturn static void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fputs("abort: ", stderr); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +static char * +mangle(char *variable) +{ + char *p; + size_t pos; + + /* Remove extension. */ + if ((p = strrchr(variable, '.'))) + *p = '\0'; + + /* Remove disallowed characters. */ + while ((pos = strspn(variable, charset)) != strlen(variable)) + variable[pos] = '_'; + + return variable; +} + +static void +indent(void) +{ + for (int i = 0; i < findent; ++i) + putchar(findentchar); +} + +static void +put(int ch) +{ + printf("0x%02hhx", (unsigned char)ch); +} + +static void +process(const char *input, const char *variable) +{ + FILE *fp; + int ch, col = 0; + + if (strcmp(input, "-") == 0) + fp = stdin; + else if (!(fp = fopen(input, "rb"))) + die("%s: %s\n", input, strerror(errno)); + + if (fstatic) + printf("static "); + if (fconst) + printf("const "); + + printf("unsigned char %s[] = {\n", variable); + + for (ch = fgetc(fp); ch != EOF; ) { + if (col == 0) + indent(); + + put(ch); + + if ((ch = fgetc(fp)) != EOF || fnull) + printf(",%s", col < 3 ? " " : ""); + + if (++col == 4) { + col = 0; + putchar('\n'); + } + + /* Add final '\0' if required. */ + if (ch == EOF && fnull) { + if (col++ == 0) + indent(); + + put(0); + } + } + + if (col != 0) + printf("\n"); + + puts("};"); + fclose(fp); +} + +int +main(int argc, char **argv) +{ + int ch; + + while ((ch = getopt(argc, argv, "0cI:i:s")) != -1) { + switch (ch) { + case '0': + fnull = 1; + break; + case 'c': + fconst = 1; + break; + case 'I': + findentchar = '\t'; + findent = atoi(optarg); + break; + case 'i': + findentchar = ' '; + findent = atoi(optarg); + break; + case 's': + fstatic = 1; + break; + default: + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 2) + usage(); + + process(argv[0], mangle(argv[1])); +}