You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lnav/src/bin2c.c

216 lines
4.6 KiB
C

// 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
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <libgen.h>
#include <unistd.h>
#include <sys/stat.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], cname[PATH_MAX];
argc -= 1;
argv += 1;
snprintf(hname, sizeof(hname), "%s.h", out_base_name);
FILE *hfile = fopen(hname, "wb");
if (hfile == NULL)
{
fprintf(stderr, "cannot open %s for writing\n", hname);
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);
fclose(hfile);
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;
}