2011-07-17 16:41:41 +00:00
|
|
|
// bin2c.c
|
|
|
|
//
|
|
|
|
// convert a binary file into a C source vector
|
|
|
|
//
|
|
|
|
// THE "BEER-WARE LICENSE" (Revision 3.1415):
|
2022-03-16 22:38:08 +00:00
|
|
|
// 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
|
2011-07-17 16:41:41 +00:00
|
|
|
|
2022-02-19 23:35:40 +00:00
|
|
|
#ifdef __CYGWIN__
|
2022-03-16 22:38:08 +00:00
|
|
|
# include <alloca.h>
|
2022-02-19 23:35:40 +00:00
|
|
|
#endif
|
|
|
|
|
2011-07-17 16:41:41 +00:00
|
|
|
#include <ctype.h>
|
2020-12-30 21:49:29 +00:00
|
|
|
#include <fcntl.h>
|
2022-03-16 22:38:08 +00:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <libgen.h>
|
2011-07-17 16:41:41 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2020-12-30 21:49:29 +00:00
|
|
|
#include <sys/stat.h>
|
2022-03-16 22:38:08 +00:00
|
|
|
#include <unistd.h>
|
2020-12-30 21:49:29 +00:00
|
|
|
#include <zlib.h>
|
2011-07-17 16:41:41 +00:00
|
|
|
|
|
|
|
#ifndef PATH_MAX
|
2022-03-16 22:38:08 +00:00
|
|
|
# define PATH_MAX 1024
|
2011-07-17 16:41:41 +00:00
|
|
|
#endif
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* name = NULL;
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
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";
|
2011-07-17 16:41:41 +00:00
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
struct file_meta {
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* fm_name;
|
2020-12-30 21:49:29 +00:00
|
|
|
unsigned int fm_compressed_size;
|
|
|
|
unsigned int fm_size;
|
|
|
|
};
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
|
|
|
symname(char* dst, const char* fname)
|
2011-07-17 16:41:41 +00:00
|
|
|
{
|
2019-05-15 16:13:56 +00:00
|
|
|
strcpy(dst, fname);
|
|
|
|
for (int lpc = 0; dst[lpc]; lpc++) {
|
|
|
|
if (!isalnum(dst[lpc])) {
|
|
|
|
dst[lpc] = '_';
|
|
|
|
}
|
|
|
|
}
|
2011-07-17 16:41:41 +00:00
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
|
|
|
process(struct file_meta* fm, FILE* ofile)
|
2011-07-17 16:41:41 +00:00
|
|
|
{
|
2020-12-30 21:49:29 +00:00
|
|
|
struct stat st;
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
if (stat(fm->fm_name, &st) == -1) {
|
|
|
|
perror("unable to stat file");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
unsigned char* buf = malloc(st.st_size);
|
|
|
|
unsigned char* dest = malloc(st.st_size);
|
2020-12-30 21:49:29 +00:00
|
|
|
|
|
|
|
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;
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
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);
|
2011-07-17 16:41:41 +00:00
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
|
|
|
usage()
|
2011-07-17 16:41:41 +00:00
|
|
|
{
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(stderr, "usage: bin2c [-n name] <output_file> [input_file1 ...]\n");
|
|
|
|
exit(1);
|
2011-07-17 16:41:41 +00:00
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
int
|
|
|
|
main(int argc, char** argv)
|
2011-07-17 16:41:41 +00:00
|
|
|
{
|
2019-05-15 16:13:56 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* out_base_name = argv[0];
|
2022-07-16 04:41:47 +00:00
|
|
|
char hname[PATH_MAX], hname_tmp[PATH_MAX], cname[PATH_MAX];
|
2019-05-15 16:13:56 +00:00
|
|
|
|
|
|
|
argc -= 1;
|
|
|
|
argv += 1;
|
|
|
|
|
|
|
|
snprintf(hname, sizeof(hname), "%s.h", out_base_name);
|
2022-07-16 04:41:47 +00:00
|
|
|
snprintf(hname_tmp, sizeof(hname_tmp), "%s.tmp", hname);
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2022-07-16 04:41:47 +00:00
|
|
|
FILE* hfile = fopen(hname_tmp, "w+b");
|
2022-03-16 22:38:08 +00:00
|
|
|
if (hfile == NULL) {
|
2022-07-16 04:41:47 +00:00
|
|
|
fprintf(stderr, "cannot open %s for writing\n", hname_tmp);
|
2019-05-15 16:13:56 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
snprintf(cname, sizeof(cname), "%s.cc", out_base_name);
|
2022-03-16 22:38:08 +00:00
|
|
|
FILE* cfile = fopen(cname, "wb");
|
|
|
|
if (cfile == NULL) {
|
2019-05-15 16:13:56 +00:00
|
|
|
fprintf(stderr, "cannot open %s for writing\n", cname);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
char sym[1024];
|
|
|
|
if (name) {
|
|
|
|
strcpy(sym, name);
|
|
|
|
} else {
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* in_base = basename(argv[0]);
|
2019-05-15 16:13:56 +00:00
|
|
|
|
|
|
|
symname(sym, in_base);
|
|
|
|
}
|
|
|
|
|
|
|
|
int array = argc > 1 || name;
|
2020-12-30 21:49:29 +00:00
|
|
|
char trailer[16];
|
|
|
|
|
|
|
|
if (array) {
|
|
|
|
snprintf(trailer, sizeof(trailer), "[%d]", argc);
|
|
|
|
} else {
|
|
|
|
trailer[0] = '\0';
|
|
|
|
}
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(hfile, HEADER_FMT, sym, sym, sym, trailer);
|
2022-07-16 04:41:47 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-15 16:13:56 +00:00
|
|
|
fclose(hfile);
|
2022-07-16 04:41:47 +00:00
|
|
|
if (!same) {
|
|
|
|
rename(hname_tmp, hname);
|
|
|
|
} else {
|
|
|
|
remove(hname_tmp);
|
|
|
|
}
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
fprintf(cfile, "#include \"bin2c.hh\"\n");
|
2019-05-15 16:13:56 +00:00
|
|
|
fprintf(cfile, "\n");
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
struct file_meta* meta = alloca(sizeof(struct file_meta) * argc);
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
memset(meta, 0, sizeof(struct file_meta) * argc);
|
2019-05-15 16:13:56 +00:00
|
|
|
for (int lpc = 0; lpc < argc; lpc++) {
|
2020-12-30 21:49:29 +00:00
|
|
|
meta[lpc].fm_name = argv[lpc];
|
2019-05-15 16:13:56 +00:00
|
|
|
process(&meta[lpc], cfile);
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(cfile, "struct bin_src_file %s%s = {\n", sym, trailer);
|
2019-05-15 16:13:56 +00:00
|
|
|
for (int lpc = 0; lpc < argc; lpc++) {
|
|
|
|
char sym[1024];
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
symname(sym, basename((char*) meta[lpc].fm_name));
|
2019-05-15 16:13:56 +00:00
|
|
|
fprintf(cfile, " ");
|
|
|
|
if (array) {
|
|
|
|
fprintf(cfile, "{ ");
|
|
|
|
}
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(cfile,
|
|
|
|
"\"%s\", %s_data, %d, %d",
|
|
|
|
basename((char*) meta[lpc].fm_name),
|
2020-12-30 21:49:29 +00:00
|
|
|
sym,
|
|
|
|
meta[lpc].fm_compressed_size,
|
|
|
|
meta[lpc].fm_size);
|
2019-05-15 16:13:56 +00:00
|
|
|
if (array) {
|
|
|
|
fprintf(cfile, " },");
|
|
|
|
}
|
|
|
|
fprintf(cfile, "\n");
|
|
|
|
}
|
|
|
|
fprintf(cfile, "};\n");
|
|
|
|
fclose(cfile);
|
|
|
|
|
|
|
|
return 0;
|
2011-07-17 16:41:41 +00:00
|
|
|
}
|