You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
6.8 KiB
257 lines
6.8 KiB
/*
|
|
* bin2c - compresses data files & converts the result to C source code
|
|
* Copyright (C) 1998-2000 Anders Widell <awl@hem.passagen.se>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
* This command uses the zlib library to compress each file given on
|
|
* the command line, and outputs the compressed data as C source code
|
|
* to the file 'data.c' in the current directory
|
|
*
|
|
*/
|
|
|
|
#include "../../config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef USE_LIBZ
|
|
#include <zlib.h>
|
|
#else
|
|
typedef unsigned char Bytef;
|
|
typedef unsigned long uLongf;
|
|
#endif
|
|
|
|
#define BUFSIZE 16384 /* Increase buffer size by this amount */
|
|
|
|
static Bytef *source=NULL; /* Buffer containing uncompressed data */
|
|
static Bytef *dest=NULL; /* Buffer containing compressed data */
|
|
static uLongf sourceBufSize=0; /* Buffer size */
|
|
#ifdef USE_LIBZ
|
|
static uLongf destBufSize=0; /* Buffer size */
|
|
#endif
|
|
|
|
static uLongf sourceLen; /* Length of uncompressed data */
|
|
static uLongf destLen; /* Length of compressed data */
|
|
|
|
static FILE *infile=NULL; /* The input file containing binary data */
|
|
static FILE *outfile=NULL; /* The output file 'data.c' */
|
|
|
|
static const char *programName="";
|
|
|
|
/*
|
|
* Print error message and free allocated resources
|
|
*
|
|
*/
|
|
|
|
static int
|
|
error (msg1, msg2, msg3)
|
|
char *msg1;
|
|
char *msg2;
|
|
char *msg3;
|
|
{
|
|
fprintf (stderr, "%s: %s%s%s\n", programName, msg1, msg2, msg3);
|
|
|
|
if (infile != NULL) fclose (infile);
|
|
if (outfile != NULL) fclose (outfile);
|
|
remove ("data.c");
|
|
free (dest);
|
|
free (source);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Replacement for strrchr in case it isn't present in libc
|
|
*
|
|
*/
|
|
|
|
static char *
|
|
my_strrchr (s, c)
|
|
char *s;
|
|
int c;
|
|
{
|
|
char *ptr = NULL;
|
|
|
|
while (*s) {
|
|
if (*s == c) ptr = s;
|
|
s++;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
#ifdef USE_LIBZ
|
|
/*
|
|
* NOTE: my_compress2 is taken directly from zlib 1.1.3
|
|
*
|
|
* This is for compatibility with early versions of zlib that
|
|
* don't have the compress2 function.
|
|
*
|
|
*/
|
|
|
|
/* ===========================================================================
|
|
Compresses the source buffer into the destination buffer. The level
|
|
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
|
length of the source buffer. Upon entry, destLen is the total size of the
|
|
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
|
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
|
|
|
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
|
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
|
Z_STREAM_ERROR if the level parameter is invalid.
|
|
*/
|
|
int my_compress2 (dest, destLen, source, sourceLen, level)
|
|
Bytef *dest;
|
|
uLongf *destLen;
|
|
const Bytef *source;
|
|
uLong sourceLen;
|
|
int level;
|
|
{
|
|
z_stream stream;
|
|
int err;
|
|
|
|
stream.next_in = (Bytef*)source;
|
|
stream.avail_in = (uInt)sourceLen;
|
|
#ifdef MAXSEG_64K
|
|
/* Check for source > 64K on 16-bit machine: */
|
|
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
|
#endif
|
|
stream.next_out = dest;
|
|
stream.avail_out = (uInt)*destLen;
|
|
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
|
|
|
stream.zalloc = (alloc_func)0;
|
|
stream.zfree = (free_func)0;
|
|
stream.opaque = (voidpf)0;
|
|
|
|
err = deflateInit(&stream, level);
|
|
if (err != Z_OK) return err;
|
|
|
|
err = deflate(&stream, Z_FINISH);
|
|
if (err != Z_STREAM_END) {
|
|
deflateEnd(&stream);
|
|
return err == Z_OK ? Z_BUF_ERROR : err;
|
|
}
|
|
*destLen = stream.total_out;
|
|
|
|
err = deflateEnd(&stream);
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
int
|
|
main (argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
int i;
|
|
const char *suffix;
|
|
#ifdef USE_LIBZ
|
|
int result;
|
|
#endif
|
|
unsigned j;
|
|
char *ptr;
|
|
int position;
|
|
|
|
programName = argv[0];
|
|
|
|
outfile = fopen ("data.c", "w");
|
|
if (outfile == NULL) {
|
|
fprintf (stderr, "%s: can't open 'data.c' for writing\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
suffix = argv[1];
|
|
/* Process each file given on command line */
|
|
for (i=2; i<argc; i++) {
|
|
infile = fopen (argv[i], "rb");
|
|
if (infile == NULL) return error ("can't open '", argv[i], "' for reading");
|
|
|
|
/* Read infile to source buffer */
|
|
sourceLen = 0;
|
|
while (!feof (infile)) {
|
|
if (sourceLen + BUFSIZE > sourceBufSize) {
|
|
sourceBufSize += BUFSIZE;
|
|
source = realloc (source, sourceBufSize);
|
|
if (source == NULL) return error ("memory exhausted", "", "");
|
|
}
|
|
sourceLen += fread (source+sourceLen, 1, BUFSIZE, infile);
|
|
if (ferror (infile)) return error ("error reading '", argv[i], "'");
|
|
}
|
|
fclose (infile);
|
|
|
|
#ifdef USE_LIBZ
|
|
|
|
/* (Re)allocate dest buffer */
|
|
destLen = sourceBufSize + (sourceBufSize+9)/10 + 12;
|
|
if (destBufSize < destLen) {
|
|
destBufSize = destLen;
|
|
dest = realloc (dest, destBufSize);
|
|
if (dest == NULL) return error ("memory exhausted", "", "");
|
|
}
|
|
|
|
/* Compress dest buffer */
|
|
destLen = destBufSize;
|
|
result = my_compress2 (dest, &destLen, source, sourceLen, 9);
|
|
if (result != Z_OK) return error ("error compressing '", argv[i], "'");
|
|
|
|
#else
|
|
|
|
destLen = sourceLen;
|
|
dest = source;
|
|
|
|
#endif
|
|
|
|
/* Output dest buffer as C source code to outfile */
|
|
ptr = my_strrchr (argv[i], '.');
|
|
if (ptr != NULL) *ptr = '\0';
|
|
/* use only the file 2name and throw away the path name */
|
|
position = strlen(argv[i]) - 1;
|
|
while (position && argv[i][position] != '/') position--;
|
|
if (argv[i][position] == '/') position++;
|
|
|
|
fprintf (outfile, "static const unsigned char %s_data_%s[] = {\n", argv[i] + position, suffix);
|
|
|
|
for (j=0; j<destLen-1; j++) {
|
|
switch (j%8) {
|
|
case 0:
|
|
fprintf (outfile, " 0x%02x, ", ((unsigned) dest[j]) & 0xffu);
|
|
break;
|
|
case 7:
|
|
fprintf (outfile, "0x%02x,\n", ((unsigned) dest[j]) & 0xffu);
|
|
break;
|
|
default:
|
|
fprintf (outfile, "0x%02x, ", ((unsigned) dest[j]) & 0xffu);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((destLen-1)%8 == 0) fprintf (outfile, " 0x%02x\n};\n\n", ((unsigned) dest[destLen-1]) & 0xffu);
|
|
else fprintf (outfile, "0x%02x\n};\n\n", ((unsigned) dest[destLen-1]) & 0xffu);
|
|
}
|
|
|
|
fclose (outfile);
|
|
#ifdef USE_LIBZ
|
|
free (dest);
|
|
#endif
|
|
free (source);
|
|
|
|
return 0;
|
|
}
|