diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 17:44:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 17:44:55 +0000 |
commit | 5068d34c08f951a7ea6257d305a1627b09a95817 (patch) | |
tree | 08213e2be853396a3b07ce15dbe222644dcd9a89 /tools/bin2c.c | |
parent | Initial commit. (diff) | |
download | lnav-5068d34c08f951a7ea6257d305a1627b09a95817.tar.xz lnav-5068d34c08f951a7ea6257d305a1627b09a95817.zip |
Adding upstream version 0.11.1.upstream/0.11.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | tools/bin2c.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/tools/bin2c.c b/tools/bin2c.c new file mode 100644 index 0000000..2141bf0 --- /dev/null +++ b/tools/bin2c.c @@ -0,0 +1,252 @@ +// bin2c.c +// +// convert a binary file into a C source vector +// +// THE "BEER-WARE LICENSE" (Revision 3.1415): +// sandro AT sigala DOT it wrote this file. As long as you retain this notice +// you can do whatever you want with this stuff. If we meet some day, and you +// think this stuff is worth it, you can buy me a beer in return. Sandro Sigala + +#ifdef __CYGWIN__ +# include <alloca.h> +#endif + +#include <ctype.h> +#include <fcntl.h> +#include <getopt.h> +#include <libgen.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> +#include <zlib.h> + +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +const char* name = NULL; + +static const char* HEADER_FMT + = "#ifndef bin2c_%s_h\n" + "#define bin2c_%s_h\n" + "\n" + "#include \"bin2c.hh\"\n" + "\n" + "extern struct bin_src_file %s%s;\n" + "\n" + "#endif\n" + "\n"; + +struct file_meta { + const char* fm_name; + unsigned int fm_compressed_size; + unsigned int fm_size; +}; + +void +symname(char* dst, const char* fname) +{ + strcpy(dst, fname); + for (int lpc = 0; dst[lpc]; lpc++) { + if (!isalnum(dst[lpc])) { + dst[lpc] = '_'; + } + } +} + +void +process(struct file_meta* fm, FILE* ofile) +{ + struct stat st; + + if (stat(fm->fm_name, &st) == -1) { + perror("unable to stat file"); + exit(1); + } + + unsigned char* buf = malloc(st.st_size); + unsigned char* dest = malloc(st.st_size); + + int fd = open(fm->fm_name, O_RDONLY); + if (fd == -1) { + perror("unable to open file"); + exit(1); + } + + int rc; + while ((rc = read(fd, &buf[fm->fm_size], (st.st_size - fm->fm_size))) > 0) { + fm->fm_size += rc; + } + + uLongf destLen = st.st_size; + compress(dest, &destLen, buf, st.st_size); + fm->fm_compressed_size = destLen; + + int c, col = 1; + char sym[1024]; + + symname(sym, basename((char*) fm->fm_name)); + fprintf(ofile, "static const unsigned char %s_data[] = {\n", sym); + for (int lpc = 0; lpc < destLen; lpc++) { + c = dest[lpc]; + if (col >= 78 - 6) { + fputc('\n', ofile); + col = 1; + } + fprintf(ofile, "0x%.2x, ", c); + col += 6; + } + fprintf(ofile, "0x00\n"); + fprintf(ofile, "\n};\n"); + + free(buf); + free(dest); +} + +void +usage() +{ + fprintf(stderr, "usage: bin2c [-n name] <output_file> [input_file1 ...]\n"); + exit(1); +} + +int +main(int argc, char** argv) +{ + int c; + + while ((c = getopt(argc, argv, "hn:")) != -1) { + switch (c) { + case 'n': + name = optarg; + break; + default: + usage(); + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + usage(); + } + + const char* out_base_name = argv[0]; + char hname[PATH_MAX], hname_tmp[PATH_MAX], cname[PATH_MAX]; + + argc -= 1; + argv += 1; + + snprintf(hname, sizeof(hname), "%s.h", out_base_name); + snprintf(hname_tmp, sizeof(hname_tmp), "%s.tmp", hname); + + FILE* hfile = fopen(hname_tmp, "w+b"); + if (hfile == NULL) { + fprintf(stderr, "cannot open %s for writing\n", hname_tmp); + exit(1); + } + + snprintf(cname, sizeof(cname), "%s.cc", out_base_name); + FILE* cfile = fopen(cname, "wb"); + if (cfile == NULL) { + fprintf(stderr, "cannot open %s for writing\n", cname); + exit(1); + } + + char sym[1024]; + if (name) { + strcpy(sym, name); + } else { + const char* in_base = basename(argv[0]); + + symname(sym, in_base); + } + + int array = argc > 1 || name; + char trailer[16]; + + if (array) { + snprintf(trailer, sizeof(trailer), "[%d]", argc); + } else { + trailer[0] = '\0'; + } + fprintf(hfile, HEADER_FMT, sym, sym, sym, trailer); + fflush(hfile); + rewind(hfile); + + int same = 1; + { + FILE* orig_hfile = fopen(hname, "rb"); + if (orig_hfile == NULL) { + same = 0; + } else { + while (1) { + char orig_line[1024], new_line[1024]; + + char* orig_res + = fgets(orig_line, sizeof(orig_line), orig_hfile); + char* new_res = fgets(new_line, sizeof(new_line), hfile); + + if (orig_res == NULL && new_res == NULL) { + break; + } + + if (orig_res == NULL || new_res == NULL) { + same = 0; + break; + } + + if (strcmp(orig_line, new_line) != 0) { + same = 0; + break; + } + } + } + } + fclose(hfile); + if (!same) { + rename(hname_tmp, hname); + } else { + remove(hname_tmp); + } + + fprintf(cfile, "#include \"bin2c.hh\"\n"); + fprintf(cfile, "\n"); + + struct file_meta* meta = alloca(sizeof(struct file_meta) * argc); + + memset(meta, 0, sizeof(struct file_meta) * argc); + for (int lpc = 0; lpc < argc; lpc++) { + meta[lpc].fm_name = argv[lpc]; + process(&meta[lpc], cfile); + } + + fprintf(cfile, "struct bin_src_file %s%s = {\n", sym, trailer); + for (int lpc = 0; lpc < argc; lpc++) { + char sym[1024]; + + symname(sym, basename((char*) meta[lpc].fm_name)); + fprintf(cfile, " "); + if (array) { + fprintf(cfile, "{ "); + } + fprintf(cfile, + "\"%s\", %s_data, %d, %d", + basename((char*) meta[lpc].fm_name), + sym, + meta[lpc].fm_compressed_size, + meta[lpc].fm_size); + if (array) { + fprintf(cfile, " },"); + } + fprintf(cfile, "\n"); + } + fprintf(cfile, "};\n"); + fclose(cfile); + + return 0; +} |