| #include <string.h> |
| #include <stdlib.h> |
| |
| /* |
| * gzip support routine declartions.. |
| * ========================================================= |
| */ |
| |
| #ifdef DEBUG |
| # define Trace(x) |
| # define Tracev(x) |
| # define Tracevv(x) |
| # define Tracec(c,x) |
| # define Tracecv(c,x) |
| # define DBG(x) printf x |
| #else |
| # define Trace(x) |
| # define Tracev(x) |
| # define Tracevv(x) |
| # define Tracec(c,x) |
| # define Tracecv(c,x) |
| # define DBG(x) |
| #endif |
| |
| void error(char *str) |
| { |
| DBG(("%s\n", str)); |
| } |
| |
| static unsigned char *inbuf; /* input buffer */ |
| static unsigned int insize; /* valid bytes in inbuf */ |
| static unsigned int inptr; /* index of next byte to be processed in inbuf */ |
| |
| #if !defined(DEBUG) |
| #define get_byte() (inptr < insize ? inbuf[inptr++] : 0) |
| #else |
| static unsigned char get_byte(void) |
| { |
| static int count; |
| unsigned char byte = (inptr < insize ? inbuf[inptr++] : 0); |
| #if 0 |
| printf("%02x ", byte); |
| if ((++count & 0x0f) == 0) { |
| printf("\n"); |
| } |
| #endif |
| return byte; |
| } |
| |
| #endif |
| |
| static void flush_window(void); |
| |
| static long bytes_out; /* total bytes compressed */ |
| static unsigned outcnt; /* bytes in output buffer */ |
| |
| #define WSIZE 0x8000 /* Window size must be at least 32k, and a power of two */ |
| static unsigned char window[WSIZE]; /* Sliding window buffer */ |
| |
| /* |
| * gzip declarations |
| */ |
| |
| #define OF(args) args |
| #define STATIC static |
| |
| |
| #define memzero(s, n) memset ((s), 0, (n)) |
| |
| typedef unsigned char uch; |
| typedef unsigned short ush; |
| typedef unsigned long ulg; |
| |
| |
| |
| #include "inflate.c" |
| |
| |
| /* Variables that gunzip doesn't need to see... */ |
| static unsigned char *output_ptr; |
| static unsigned long end_offset; |
| static struct unzip_region { |
| unsigned long start; |
| unsigned long end_offset; |
| } unzip_region; |
| |
| /* Data provided by the header */ |
| extern unsigned char zipped_data[]; |
| extern unsigned char zipped_data_end[]; |
| extern unsigned char entry; |
| /* Assembly language routines */ |
| extern void jmp_to_program_entry(void *); |
| |
| /* =========================================================================== |
| * Write the output window window[0..outcnt-1] and update crc and bytes_out. |
| * (Used for the decompressed data only.) |
| */ |
| static void flush_window(void) |
| { |
| ulg c = crc; /* temporary variable */ |
| unsigned n; |
| unsigned long limit; |
| uch *in, *out, ch; |
| |
| limit = outcnt; |
| |
| |
| n = 0; |
| in = window; |
| while (n < outcnt) { |
| limit = end_offset - bytes_out +n; |
| if (limit > outcnt) { |
| limit = outcnt; |
| } |
| out = output_ptr; |
| DBG(("flush 0x%08lx start 0x%08lx limit 0x%08lx\n", |
| (unsigned long) out, (unsigned long)n, limit)); |
| for (; n < limit; n++) { |
| ch = *out++ = *in++; |
| c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8); |
| } |
| crc = c; |
| bytes_out += (out - output_ptr); |
| output_ptr = out; |
| if (bytes_out == end_offset) { |
| if (output_ptr == (unsigned char *)(&unzip_region+1)) { |
| output_ptr = (unsigned char *)(unzip_region.start); |
| end_offset = unzip_region.end_offset; |
| } else { |
| output_ptr = (unsigned char *)&unzip_region; |
| end_offset += sizeof(unzip_region); |
| } |
| } |
| } |
| outcnt = 0; |
| } |
| |
| |
| void gunzip_setup(void) |
| { |
| DBG(("gunzip_setup\n")); |
| outcnt = 0; |
| bytes_out = 0; |
| |
| end_offset = sizeof(unzip_region); |
| output_ptr = (unsigned char *)&unzip_region; |
| |
| inbuf = &zipped_data[0]; |
| insize = zipped_data_end - zipped_data; |
| inptr = 0; |
| |
| makecrc(); |
| DBG(("gunzip_setup_done\n")); |
| } |
| |
| |
| int kunzip(int argc, char **argv) |
| { |
| DBG(("kunzip\n")); |
| gunzip_setup(); |
| DBG(("pre_gunzip\n")); |
| if (gunzip() != 0) { |
| error("gunzip failed"); |
| while(1) {} |
| return -1; |
| } |
| DBG(("pre_jmp_to_program_entry: %p\n", &entry )); |
| jmp_to_program_entry(&entry); |
| return 0; |
| } |