X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=compress.c;h=91f0d0e1d1ea993550114da81dc9664796f2576b;hb=5f83300ce6a5da27e68085bddce47b736cfdea79;hp=d0d411a4a4dab9959d3eca178d142a8bc7f7bceb;hpb=58352bb03181bec09abf991ae982bc3bb04c5fd3;p=compress.git diff --git a/compress.c b/compress.c index d0d411a..91f0d0e 100644 --- a/compress.c +++ b/compress.c @@ -1,81 +1,71 @@ /* depend: */ /* cflags: */ -/* linker: */ +/* linker: code.o debug.o fprintf.o */ -#include -#include #include #include -#include -#include +#include "code.h" +#include "debug.h" +#include "fprintf.h" /* constants */ -#define COMPRESS 1 -#define DECOMPRESS 2 - -#define NB_CHARS 256 #define BUFFER_SIZE 4096 -#define DEBUG 4 -#define INFO 3 -#define WARNING 2 -#define ERROR 1 - /* macros */ -#define CEIL(x, y) (((x) + (y) - 1) / (y)) -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) -#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0) -#define PRINTF(args...) do { fprintf (stdout, args); fflush (stdout); } while (0) - /* gobal variables */ char *progname = NULL; -int verbose = 2; /* help function */ void usage (int ret) { FILE *fd = ret ? stderr : stdout; - fprintf (fd, "usage: %s\n", progname); - fprintf (fd, " -h : help message\n"); - fprintf (fd, " -i : input file\n"); - fprintf (fd, " -o : output file\n"); - fprintf (fd, " -v : verbose level (%d)\n", verbose); + _fprintf (fd, "usage: %s\n", progname); + _fprintf (fd, " -h : help message\n"); + _fprintf (fd, " -i : input file\n"); + _fprintf (fd, " -o : output file\n"); + _fprintf (fd, " -v : verbose level (%d)\n", verbose); exit (ret); } +void blkcpy (void *dst, const void *src, int len) +{ + while (len--) { + *((char *)dst++) = *((char *)src++); + } +} + /* create occurence table */ int *create_table (char *filename) { - char buffer[BUFFER_SIZE] = {0}; + byte_t buffer[BUFFER_SIZE] = {0}; int nbread; int *table = NULL; FILE *fid = NULL; - VERBOSE (DEBUG, PRINTF ("start create occurence table\n")); + VERBOSE (DEBUG, PRINTF ("start creating occurence table\n")); /* memory allocation */ - table = (int *) calloc (NB_CHARS, sizeof (int)); + table = (int *) calloc (NB_BYTES, sizeof (int)); if (table == NULL) { - VERBOSE (ERROR, printf ("can't allocate memory\n")); + VERBOSE (ERROR, _fprintf (stdout, "can't allocate memory\n")); return NULL; } - VERBOSE (INFO, printf ("memory allocated\n")); + VERBOSE (INFO, _fprintf (stdout, "memory allocated\n")); /* open file */ fid = fopen (filename, "rb"); if (fid == NULL) { - VERBOSE (ERROR, printf ("can't open file '%s'\n", filename)); + VERBOSE (ERROR, _fprintf (stdout, "can't open file '%s'\n", filename)); free (table); return NULL; } - VERBOSE (INFO, printf ("file '%s' opened\n", filename)); + VERBOSE (INFO, _fprintf (stdout, "file '%s' opened\n", filename)); /* read file */ while (!feof (fid)) { @@ -89,7 +79,7 @@ int *create_table (char *filename) /* close file */ fclose (fid); - VERBOSE (DEBUG, PRINTF ("end create occurence table\n")); + VERBOSE (DEBUG, PRINTF ("end creating occurence table\n")); return table; } @@ -100,10 +90,10 @@ void print_occ_table (int *table) { int i; - printf ("Occurence table\n"); - for (i = 0; i < NB_CHARS; i++) { + _fprintf (stdout, "Occurence table\n"); + for (i = 0; i < NB_BYTES; i++) { if (table[i]) { - printf ("0x%02x '%c': %d\n", i, ((i < 32) || (i > 127)) ? '.' : i, table[i]); + _fprintf (stdout, "0x%02x '%c': %d\n", i, ((i < 32) || (i > 127)) ? '.' : i, table[i]); } } } @@ -115,7 +105,7 @@ typedef struct _leaf_t struct _leaf_t *left; struct _leaf_t *right; int occ; - char c; + byte_t c; } leaf_t; /* initialize forest */ @@ -129,7 +119,7 @@ leaf_t **init_forest (int *table) VERBOSE (DEBUG, PRINTF ("start initiliazing forest\n")); /* count number of leafs */ - for (i = 0; i < NB_CHARS; i++) { + for (i = 0; i < NB_BYTES; i++) { if (table[i] > 0) { nb_leafs++; } @@ -138,16 +128,16 @@ leaf_t **init_forest (int *table) /* allocate memory */ leafs = (leaf_t **) calloc (nb_leafs + 1, sizeof (leaf_t *)); if (leafs == NULL) { - VERBOSE (ERROR, printf ("can't allocate memory\n")); + VERBOSE (ERROR, _fprintf (stdout, "can't allocate memory\n")); return NULL; } /* initialize leafs */ - for (i = 0, l = 0; i < NB_CHARS; i++) { + for (i = 0, l = 0; i < NB_BYTES; i++) { if (table[i] > 0) { leafs[l] = (leaf_t *) calloc (1, sizeof (leaf_t)); if (leafs[l] == NULL) { - VERBOSE (ERROR, printf ("can't allocate memory\n")); + VERBOSE (ERROR, _fprintf (stdout, "can't allocate memory\n")); return NULL; } leafs[l]->occ = table[i]; @@ -167,7 +157,8 @@ leaf_t *create_tree (leaf_t **leafs) { leaf_t *branch = NULL; int nb_leafs = 0; - int last, ante; + int last = -1; + int ante; int i, j; VERBOSE (DEBUG, PRINTF ("start creating tree\n")); @@ -204,12 +195,12 @@ leaf_t *create_tree (leaf_t **leafs) /* create branch */ if ((last == -1) || (ante == -1)) { - VERBOSE (ERROR, printf ("error during tree building\n")); + VERBOSE (ERROR, _fprintf (stdout, "error during tree building\n")); return NULL; } branch = (leaf_t *) calloc (1, sizeof (leaf_t)); if (branch == NULL) { - VERBOSE (ERROR, printf ("can't allocate memory\n")); + VERBOSE (ERROR, _fprintf (stdout, "can't allocate memory\n")); return NULL; } branch->left = leafs[last]; @@ -221,7 +212,7 @@ leaf_t *create_tree (leaf_t **leafs) VERBOSE (DEBUG, PRINTF ("end creating tree\n")); - return leafs[last]; + return (last != -1) ? leafs[last] : NULL; } /* free tree */ @@ -238,23 +229,17 @@ void free_tree (leaf_t *root) { } } -/* code structure */ - -typedef struct { - char code[NB_CHARS - 1 + 1]; -} code_t; - /* explore tree */ void explore_tree (code_t *table, leaf_t *root, char *code, int index) { if ((root->left == NULL) && (root->right == NULL)) { - strcpy ((char *)(table + (int)(root->c)), code); + codcpy ((char *)(table + (int)(root->c)), sizeof (code_t), code); } else { - strcpy (code + index, "1"); + codcpy (code + index, sizeof (code_t), "1"); explore_tree (table, root->left, code, index + 1); - strcpy (code + index, "0"); + codcpy (code + index, sizeof (code_t), "0"); explore_tree (table, root->right, code, index + 1); } } @@ -269,9 +254,9 @@ code_t *create_code (leaf_t *root) VERBOSE (DEBUG, PRINTF ("start creating code table\n")); /* allocate table */ - table = (code_t *) calloc (NB_CHARS, sizeof (code_t)); + table = (code_t *) calloc (NB_BYTES, sizeof (code_t)); if (table == NULL) { - VERBOSE (ERROR, printf ("can't allocate memory\n")); + VERBOSE (ERROR, _fprintf (stdout, "can't allocate memory\n")); return NULL; } @@ -289,24 +274,24 @@ void print_code_table (code_t *codes) char *code; int i; - printf ("Code table\n"); - for (i = 0; i < NB_CHARS; i++) { + _fprintf (stdout, "Code table\n"); + for (i = 0; i < NB_BYTES; i++) { code = (char *)(codes + i); - if (strlen (code) == 0) { + if (codlen (code) == 0) { continue; } - printf ("0x%02x '%c': %s\n", i, ((i < 32) || (i > 127)) ? '.' : i, code); + _fprintf (stdout, "0x%02x '%c': %s\n", i, ((i < 32) || (i > 127)) ? '.' : i, code); } } /* encode header and code table */ -char *encode_header_table (code_t *codes, int *occ) +byte_t *encode_header_table (code_t *codes, int *occ) { - unsigned char buffer[NB_CHARS * (NB_CHARS - 1) / 2 / 8 + NB_CHARS + 2] = {0}; - char bits[(NB_CHARS - 1) + 8 + 1] = {0}; + byte_t buffer[NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES + 6] = {0}; + char bits[(NB_BYTES - 1) + 8 + 1] = {0}; char *code; - unsigned char *header = buffer; + byte_t *header = buffer; int i, j, length, mode; int nb = 0; int size = 0; @@ -314,131 +299,135 @@ char *encode_header_table (code_t *codes, int *occ) VERBOSE (DEBUG, PRINTF ("start encoding header and code table\n")); /* mode 1 or 2 */ - for (i = 0; i < NB_CHARS; i++) { + for (i = 0; i < NB_BYTES; i++) { code = (char *)(codes + i); - if (strlen (code) > 0) { + if (codlen (code) > 0) { nb++; - size += strlen (code) * occ[i]; + size += codlen (code) * occ[i]; } } - mode = (NB_CHARS < 2 * nb + 1) ? 1 : 2; + mode = (NB_BYTES < 2 * nb + 1) ? 1 : 2; VERBOSE (DEBUG, PRINTF ("nb chars: %d\n", nb)); VERBOSE (DEBUG, PRINTF ("mode: %d\n", mode)); VERBOSE (DEBUG, PRINTF ("size: %d\n", size)); + VERBOSE (DEBUG, PRINTF ("rem: %d\n", size % 256)); /* header */ - strcpy ((char *)header, (mode == 1) ? "MZ1 " : "MZ2 "); + codcpy ((char *)header, sizeof (buffer), (mode == 1) ? "MZ1 " : "MZ2 "); header += 6; /* size */ switch (mode) { case 1: - for (i = 0; i < NB_CHARS; i++) { + for (i = 0; i < NB_BYTES; i++) { code = (char *)(codes + i); - *(header++) = (unsigned char) strlen (code); + *(header++) = (byte_t) codlen (code); } break; case 2: - *(header++) = (unsigned char)(nb - 1); - for (i = 0; i < NB_CHARS; i++) { + *(header++) = (byte_t)(nb - 1); + for (i = 0; i < NB_BYTES; i++) { code = (char *)(codes + i); - if (strlen (code) > 0) { - *(header++) = (unsigned char)i; - *(header++) = (unsigned char) strlen (code); + if (codlen (code) > 0) { + *(header++) = (byte_t) i; + *(header++) = (byte_t) codlen (code); } } break; } /* bits */ - for (i = 0; i < NB_CHARS; i++) { + for (i = 0; i < NB_BYTES; i++) { code = (char *)(codes + i); - if (strlen (code) > 0) { - strcat (bits, code); - while (strlen (bits) > (8 - 1)) { + if (codlen (code) > 0) { + codcat (bits, sizeof (code_t), code); + while (codlen (bits) > (8 - 1)) { for (j = 0; j < 8; j++) { *header <<= 1; if (bits[j] == '1') { (*header)++; } } - strcpy (bits, bits + 8); + codcpy (bits, sizeof (code_t), bits + 8); header++; } } } - if (strlen (bits) > 0) { - for (j = 0; j < (int)strlen (bits); j++) { + if (codlen (bits) > 0) { + for (j = 0; j < (int)codlen (bits); j++) { *header <<= 1; if (bits[j] == '1') { (*header)++; } } + for (j = (int)codlen (bits); j < 8; j++) { + *header <<= 1; + } header++; } /* length */ length = (int)(header - buffer - 6); VERBOSE (DEBUG, PRINTF ("lengh: %d %02x %02x\n", length, length >> 8, length & 0xff)); - buffer[3] = (unsigned char)(length >> 8); - buffer[4] = (unsigned char)(length & 0xff); - buffer[5] = (unsigned char)(size % 8); + buffer[3] = (byte_t)(length >> 8); + buffer[4] = (byte_t)(length & 0xff); + buffer[5] = (byte_t)(size % 256); /* allocation */ - header = (unsigned char *) calloc (length + 6, 1); - memcpy (header, buffer, length + 6); + header = (byte_t *) calloc (length + 6, 1); + blkcpy (header, buffer, length + 6); VERBOSE (DEBUG, PRINTF ("end encoding header and code table\n")); - return (char *)header; + return header; } /* print header */ -void print_header (char *header) +void print_header (byte_t *header) { int length, i; - length = ((unsigned char)(header[3]) << 8) + (unsigned char)(header[4]); + length = (header[3] << 8) + header[4]; VERBOSE (DEBUG, PRINTF ("lengh: %d\n", length)); for (i = 0; i < length + 6; i++) { - printf ("%02x", (unsigned char)header[i]); + _fprintf (stdout, "%02x", header[i]); } - printf ("\n"); + _fprintf (stdout, "\n"); } /* write crompressed file */ -int write_compress (char *output, char *input, code_t *codes, char *header) +int write_compress (char *output, char *input, code_t *codes, byte_t *header) { - char bufin[BUFFER_SIZE] = {0}; - char bufout[BUFFER_SIZE] = {0}; - char bits[(NB_CHARS - 1) + 8 + 1] = {0}; + byte_t bufin[BUFFER_SIZE] = {0}; + byte_t bufout[BUFFER_SIZE] = {0}; + char bits[(NB_BYTES - 1) + 8 + 1] = {0}; FILE *fin, *fout; int length = 0; int i, j, nbread; - char *pt; + byte_t *pt; VERBOSE (DEBUG, PRINTF ("start writting compressed file\n")); /* open input file */ fin = fopen (input, "rb"); if (fin == NULL) { - VERBOSE (ERROR, printf ("can't open file '%s'\n", input)); + VERBOSE (ERROR, _fprintf (stdout, "can't open file '%s' for reading\n", input)); return 1; } - VERBOSE (INFO, printf ("file '%s' opened\n", input)); + VERBOSE (INFO, _fprintf (stdout, "file '%s' opened\n", input)); /* open output file */ fout = fopen (output, "wb"); if (fin == NULL) { - VERBOSE (ERROR, printf ("can't open file '%s'\n", output)); + VERBOSE (ERROR, _fprintf (stdout, "can't open file '%s' for writing\n", output)); return 1; } - VERBOSE (INFO, printf ("file '%s' opened\n", output)); + VERBOSE (INFO, _fprintf (stdout, "file '%s' opened\n", output)); /* write header */ - length = ((unsigned char)(header[3]) << 8) + (unsigned char)(header[4]); + length = (header[3] << 8) + header[4]; VERBOSE (DEBUG, PRINTF ("lengh: %d\n", length)); fwrite (header, 1, length + 6, fout); @@ -448,40 +437,39 @@ int write_compress (char *output, char *input, code_t *codes, char *header) nbread = fread (bufin, 1, BUFFER_SIZE, fin); VERBOSE (DEBUG, PRINTF ("nbread: %d\n", nbread)); for (i = 0; i < nbread; i++) { - strcat (bits, (char *)(codes + bufin[i])); - while (strlen (bits) > (8 - 1)) { + codcat (bits, sizeof (code_t), (char *)(codes + bufin[i])); + while (codlen (bits) > (8 - 1)) { for (j = 0; j < 8; j++) { *pt <<= 1; if (bits[j] == '1') { (*pt)++; } } - strcpy (bits, bits + 8); - if (pt - bufout < BUFFER_SIZE) { - pt++; - } else { + codcpy (bits, sizeof (code_t), bits + 8); + if (pt - bufout == BUFFER_SIZE - 1) { fwrite (bufout, 1, BUFFER_SIZE, fout); pt = bufout; + } else { + pt++; } } } } - if (strlen (bits) > 0) { - for (j = 0; j < (int)strlen (bits); j++) { + VERBOSE (DEBUG, PRINTF ("lastest bits : %d\n", codlen (bits))); + if (codlen (bits) > 0) { + for (j = 0; j < (int)codlen (bits); j++) { *pt <<= 1; if (bits[j] == '1') { (*pt)++; } } - if (pt - bufout < BUFFER_SIZE) { - pt++; - } else { - fwrite (bufout, 1, BUFFER_SIZE, fout); - pt = bufout; + for (j = (int)codlen (bits); j < 8; j++) { + *pt <<= 1; } pt++; } if (pt != bufout) { + VERBOSE (DEBUG, PRINTF ("last partial buffer written: %u\n", pt - bufout)); fwrite (bufout, 1, pt - bufout, fout); } @@ -494,6 +482,210 @@ int write_compress (char *output, char *input, code_t *codes, char *header) return 0; } +/* read header */ + +code_t *read_header (char *filename) { + byte_t buffer[NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES + 6] = {0}; + code_t *table = NULL; + byte_t *codes = NULL; + byte_t cur; + int lengths[NB_BYTES] = {0}; + FILE *fid = NULL; + int mode = 0; + size_t i, j, l, nb, size; + + VERBOSE (DEBUG, PRINTF ("start reading header\n")); + + /* open file */ + fid = fopen (filename, "rb"); + if (fid == NULL) { + VERBOSE (ERROR, _fprintf (stdout, "can't open file '%s'\n", filename)); + return NULL; + } + VERBOSE (INFO, _fprintf (stdout, "file '%s' opened\n", filename)); + + /* read magic number */ + nb = fread (buffer, 1, 6, fid); + VERBOSE (DEBUG, PRINTF ("nb, buffer: %d 0x%02x 0x%02x\n", nb, buffer[0], buffer[1])); + if ((nb == 6) && (buffer[0] == 'M') && (buffer[1] == 'Z')) { + mode = (buffer[2] == '1') ? 1 : (buffer[2] == '2') ? 2 : 0; + size = (buffer[3] << 8) + buffer[4]; + VERBOSE (DEBUG, PRINTF ("mode, size: %d %d\n", mode, size)); + if (size > NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES) { + mode = 0; + } else { + nb = fread (buffer, 1, size, fid); + VERBOSE (DEBUG, PRINTF ("nb read: %d\n", nb)); + if (nb != size) { + mode = 0; + } + } + } + fclose (fid); + if (mode == 0) { + VERBOSE (ERROR, _fprintf (stdout, "incorrect file\n")); + return NULL; + } + + /* analyse header */ + codes = buffer; + switch (mode) { + case 1: + for (i = 0; i < NB_BYTES; i++) { + lengths[i] = *(codes++); + } + break; + case 2: + nb = *(codes++) + 1; + VERBOSE (DEBUG, PRINTF ("nb codes: %d\n", nb)); + for (i = 0; i < nb; i++) { + j = *(codes++); + lengths[j] = *(codes++); + } + break; + } + VERBOSE (DEBUG, for (i = 0; i < NB_BYTES; i++) if (lengths[i]) PRINTF ("%d: %d\n", i, lengths[i])); + + /* check lengths */ + for (i = 0, l = 0; i < NB_BYTES; i++) { + l += lengths[i]; + } + if (((mode == 1) && (size - 256 != (l + 7) / 8)) || + ((mode == 2) && (size - 2 * nb - 1 != (l + 7) / 8))) { + VERBOSE (ERROR, _fprintf (stdout, "incorrect code table length\n")); + return NULL; + } + + /* allocate table */ + table = (code_t *) calloc (NB_BYTES, sizeof (code_t)); + if (table == NULL) { + VERBOSE (ERROR, _fprintf (stdout, "can't allocate memory\n")); + return NULL; + } + + /* decode code */ + cur = *(codes++); + l = 8; + for (i = 0; i < NB_BYTES; i++) { + if (lengths[i] == 0) { + continue; + } + while (lengths[i]--) { + codcat ((char *)(table + i), sizeof (code_t), ((cur & 0x80) == 0) ? "0" : "1"); + l--; + cur <<= 1; + if (l == 0) { + cur = *(codes++); + l = 8; + } + } + } + + VERBOSE (DEBUG, PRINTF ("end reading header\n")); + + return table; +} + +/* write decompressed file */ + +int write_decompress (char *output, char *input, code_t *codes) +{ + byte_t bufin[BUFFER_SIZE] = {0}; + byte_t bufout[BUFFER_SIZE] = {0}; + byte_t bufhea[MAX(NB_BYTES * (NB_BYTES - 1) / 2 / 8 + NB_BYTES + 6, BUFFER_SIZE)] = {0}; + char bits[(NB_BYTES - 1) + 1] = {0}; + FILE *fin, *fout; + int i, j, k, nb, size, rem; + int is_found; + int l = 0; + byte_t *pt; + + VERBOSE (DEBUG, PRINTF ("start writing decompressed file\n")); + + /* open file for reading */ + fin = fopen (input, "rb"); + if (fin == NULL) { + VERBOSE (ERROR, _fprintf (stdout, "can't open file '%s' for reading\n", input)); + return 1; + } + VERBOSE (INFO, _fprintf (stdout, "file '%s' opened\n", input)); + + /* read magic number */ + nb = fread (bufhea, 1, 6, fin); + if (nb != 6) { + VERBOSE (ERROR, _fprintf (stdout, "can't read file\n")); + fclose (fin); + return 1; + } + size = (bufhea[3] << 8) + bufhea[4]; + VERBOSE (DEBUG, _fprintf (stdout, "table size: %d\n", size)); + rem = bufhea[5]; + VERBOSE (DEBUG, _fprintf (stdout, "remainder: %d\n", rem)); + nb = fread (bufhea, 1, size, fin); + if (nb != size) { + VERBOSE (ERROR, _fprintf (stdout, "can't read file\n")); + fclose (fin); + return 1; + } + + /* open file for writing */ + fout = fopen (output, "wb"); + if (fout == NULL) { + VERBOSE (ERROR, _fprintf (stdout, "can't open file '%s' for writing\n", output)); + return 2; + } + VERBOSE (INFO, _fprintf (stdout, "file '%s' opened\n", output)); + + /* write file */ + pt = bufout; + while (!feof (fin)) { + nb = fread (bufin, 1, BUFFER_SIZE, fin); + VERBOSE (DEBUG, PRINTF ("nbread: %d\n", nb)); + for (i = 0; i < nb; i++) { + for (j = 0; j < 8; j++) { + codcat (bits, sizeof (bits), ((bufin[i] & 0x80) == 0) ? "0" : "1"); + bufin[i] <<= 1; + l++; + VERBOSE (DEBUG, PRINTF ("bits: %d - %s\n", codlen (bits), bits)); + + /* look for correct code */ + is_found = 0; + for (k = 0; (k < NB_BYTES) && (!is_found); k++) { + if (codcmp ((char *)(codes + k), bits) == 0) { + is_found = 1; + VERBOSE (DEBUG, PRINTF ("found: %d\n", k)); + *pt= k; + bits[0] = 0; + if (pt - bufout == BUFFER_SIZE - 1) { + VERBOSE (DEBUG, PRINTF ("nb buffer out: %u\n", (pt - bufout))); + fwrite (bufout, 1, BUFFER_SIZE, fout); + pt = bufout; + } else { + pt++; + } + } + } + if ((i == nb - 1) && (l % 256 == rem) && (feof (fin))) { + VERBOSE (DEBUG, PRINTF ("break\n")); + break; + } + } + } + } + if (pt != bufout) { + VERBOSE (DEBUG, PRINTF ("nb buffer out: %u\n", (pt - bufout))); + fwrite (bufout, 1, pt - bufout, fout); + } + + /* close files */ + fclose (fin); + fclose (fout); + + VERBOSE (DEBUG, PRINTF ("end writing decompressed file\n")); + + return 0; +} + /* main function */ int main (int argc, char *argv[]) @@ -504,15 +696,23 @@ int main (int argc, char *argv[]) leaf_t **leafs = NULL; leaf_t *root = NULL; code_t *codes = NULL; - char *header = NULL; + byte_t *header = NULL; int mode = COMPRESS; - int rc = 0; + int rc = 1; progname = argv[0]; int c; - VERBOSE (DEBUG, PRINTF ("start argument processing\n")); - while ((c = getopt(argc, argv, "cdhi:o:v:")) != EOF) { + char * arg; + VERBOSE (DEBUG, PRINTF ("start processing arguments\n")); + while (argc-- > 1) { + arg = *(++argv); + if (arg[0] != '-') { + _fprintf (stderr, "%s: invalid option -- %s\n", progname, arg); + usage (1); + } + c = arg[1]; + VERBOSE (DEBUG, PRINTF ("option: %c\n", c)); switch (c) { case 'c': mode = COMPRESS; @@ -521,29 +721,32 @@ int main (int argc, char *argv[]) mode = DECOMPRESS; break; case 'i': - VERBOSE (DEBUG, PRINTF ("-i\n")); - VERBOSE (DEBUG, PRINTF ("optarg: %s\n", optarg)); - input = optarg; + input = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL; + VERBOSE (DEBUG, PRINTF ("input: %s\n", input)); break; case 'o': - VERBOSE (DEBUG, PRINTF ("-o\n")); - output = optarg; + output = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL; + VERBOSE (DEBUG, PRINTF ("output: %s\n", output)); break; case 'v': - VERBOSE (DEBUG, PRINTF ("-v\n")); - verbose = atoi (optarg); - VERBOSE (INFO, printf ("verbose: %d\n", verbose)); + arg = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL; + if (arg == NULL) { + _fprintf (stderr, "%s: missing verbose level\n", progname); + usage (1); + } + verbose = atoi (arg); + VERBOSE (INFO, _fprintf (stdout, "verbose: %d\n", verbose)); break; case 'h': default: usage (c != 'h'); } } - if (argc - optind != 0) { - fprintf (stderr, "%s: invalid option -- %s\n", progname, argv[optind]); + if ((input == NULL) || (output == NULL)) { + _fprintf (stderr, "%s: missing file\n", progname); usage (1); } - VERBOSE (DEBUG, PRINTF ("end argument processing\n")); + VERBOSE (DEBUG, PRINTF ("end processing arguments\n")); switch (mode) { case COMPRESS: @@ -564,11 +767,15 @@ int main (int argc, char *argv[]) rc = write_compress (output, input, codes, header); break; case DECOMPRESS: - rc = 1; + codes = read_header (input); + if (codes == NULL) break; + VERBOSE (INFO, print_code_table (codes)); + rc = write_decompress (output, input, codes); break; } /* clean everything */ + fflush (stdout); if (header) free (header); if (codes) free (codes); if (root) free_tree (root); @@ -582,5 +789,10 @@ int main (int argc, char *argv[]) // test: compress.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }' // test: compress.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }' // test: compress.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }' +// test: compress.exe -c -i compress.c -o compress.mz +// test: ls -sS1 compress.c compress.mz | tail -1 | grep compress.mz +// test: compress.exe -d -i compress.mz -o tmp.c +// test: cmp compress.c tmp.c +// test: rm compress.mz tmp.c -// vim: ts=4 sw=4 et +/* vim: set ts=4 sw=4 et */