OSDN Git Service

prepared to support -lh6- and -lh7- methods
authorKoji Arai <jca02266@gmail.com>
Mon, 10 Mar 2008 17:23:12 +0000 (02:23 +0900)
committerKoji Arai <jca02266@gmail.com>
Mon, 10 Mar 2008 17:23:12 +0000 (02:23 +0900)
ar.c
ar.h
decode.c
encode.c
huf.c
makefile
tests/.gitignore [new file with mode: 0644]
tests/lha-test2

diff --git a/ar.c b/ar.c
index d68a9b7..751dc8c 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -59,13 +59,46 @@ struct lzh_header {
     char os_id;
 };
 
+struct lha_method methods[] = {
+           /* id, dicbit, pbit, maxmatch */
+           /* note: dicbit == 0 means no compress */
+    /*0*/ {"-lh0-", 0,  0,  0},        /* no compress */
+    /*1*/ {"-lh1-", 12, 0, 60},        /* 2^12 =  4KB dynamic huffman (LHarc) */
+    /*2*/ {"-lh2-", 13, 0,256},        /* 2^13 =  8KB dynamic huffman */
+    /*3*/ {"-lh3-", 13, 0,256},        /* 2^13 =  8KB static huffman */
+    /*4*/ {"-lh4-", 12, 4,256},        /* 2^12 =  4KB static huffman (pos and len)*/
+    /*5*/ {"-lh5-", 13, 4,256},        /* 2^13 =  8KB static huffman (pos and len)*/
+    /*6*/ {"-lh6-", 15, 5,256},        /* 2^15 = 32KB static huffman (pos and len)*/
+    /*7*/ {"-lh7-", 16, 5,256},        /* 2^16 = 64KB static huffman (pos and len)*/
+    /*8*/ {"-lzs-", 11, 0, 17},        /* 2^11 =  2KB (LArc) */
+    /*9*/ {"-lz5-", 12, 0, 17},        /* 2^12 =  4KB (LArc) */
+    /*10*/{"-lz4-", 0,  0,  0},        /* no compress (LArc) */
+    /*11*/{"-lzd-", 0,  0,  0},        /* directory */
+};
+
 struct lha_opts opts;
 
+struct lha_method *
+which_method(char *id)
+{
+    int i;
+
+    for (i = 0; i < sizeof(methods)/sizeof(methods[0]); i++) {
+        if (strncmp(id, methods[i].id, sizeof(methods[0].id)) == 0) {
+            return &methods[i];
+        }
+    }
+    return NULL;
+}
+
 init_opts()
 {
     opts.nocompress = 0;
     opts.outdir = NULL;
     opts.quiet = 0;
+
+    /* default is the -lh5- method */
+    opts.method   = &methods[5];
 }
 
 #define FNAME_MAX (255 - 25)    /* max strlen(filename) */
@@ -324,7 +357,7 @@ add(int replace_flag, char *filename)
     h.namelen = strlen(filename);
 
     headersize = 25 + h.namelen;
-    memcpy(h.method, "-lh5-", 5);  /* compress */
+    memcpy(h.method, opts.method->id, sizeof(h.method));  /* compress */
 
     headerpos = ftell(outfile);
     write_header(outfile, headersize, &h);
@@ -377,7 +410,7 @@ get_line(char *s, int n)
 static void
 extract(int to_file, struct lzh_header *h)
 {
-    int n, method;
+    int n;
     uint ext_headersize;
     uchar buffer[DICSIZ];
 
@@ -400,19 +433,18 @@ extract(int to_file, struct lzh_header *h)
             printf("===== %s =====\n", h->filename);
     }
     crc = INIT_CRC;
-    method = h->method[3];      /* -lh*5*- */
-    h->method[3] = ' ';
-    if (!strchr("045", method) || memcmp("-lh -", h->method, 5)) {
-        fprintf(stderr, "Unknown method: %u\n", method);
+    opts.method = which_method(h->method);
+    if (opts.method == NULL) {
+        fprintf(stderr, "Unknown method: %.5s\n", h->method);
         skip(arcfile, h);
     }
     else {
         crc = INIT_CRC;
-        if (method != '0')
+        if (opts.method->dicbit != 0)
             decode_start();
         while (h->origsize != 0) {
             n = (uint) ((h->origsize > DICSIZ) ? DICSIZ : h->origsize);
-            if (method != '0')
+            if (opts.method->dicbit != 0)
                 decode(n, buffer);
             else if (fread((char *) buffer, 1, n, arcfile) != n)
                 error("Can't read");
@@ -522,13 +554,26 @@ parse_args(int argc, char **argv)
             {0, 0, 0, 0}
         };
 
-        c = getopt_long(argc, argv, "q[012]w:z", long_options, &option_index);
+        c = getopt_long(argc, argv, "o[567]q[012]w:z",
+                        long_options, &option_index);
 
         if (c == -1) break;
 
         switch (c) {
         case 0:                 /* set vallue by long option */
             break;
+        case 'o':               /* compress method */
+            {
+                int idx;
+
+                if (optarg)
+                    idx = *optarg - '0'; /* -lh[567]- method */
+                else
+                    idx = 1;    /* -lh1- method */
+
+                opts.method   = &methods[idx];
+            }
+            break;
         case 'q':               /* quiet mode */
             opts.quiet = 2;     /* level 2 */
             if (optarg)
@@ -573,6 +618,8 @@ main(int argc, char *argv[])
     char *archive_file;
     struct lzh_header h;
 
+    init_opts();
+
     if (argv[1] == 0)
         print_usage();
 
diff --git a/ar.h b/ar.h
index a2dc352..1b9d695 100644 (file)
--- a/ar.h
+++ b/ar.h
@@ -8,10 +8,20 @@ typedef unsigned int uint;      /* 16 bits or more */
 typedef unsigned short ushort;  /* 16 bits or more */
 typedef unsigned long ulong;    /* 32 bits or more */
 
+struct lha_method {
+    char *id;
+    int dicbit;
+    int pbit;
+    int maxmatch;
+};
+
 struct lha_opts {
     int nocompress;
     char *outdir;
     int quiet;
+
+    /* compress parameter */
+    struct lha_method *method;
 };
 
 /* ar.c */
@@ -60,8 +70,8 @@ void decode(uint count, uchar text[]);
 
 extern ushort left[], right[];
 
-void huf_encode_start(void);
-void huf_decode_start(void);
+void huf_encode_start(struct lha_method *m);
+void huf_decode_start(struct lha_method *m);
 uint decode_c(void);
 uint decode_p(void);
 void output(uint c, uint p);
index 2259de2..6715b98 100644 (file)
--- a/decode.c
+++ b/decode.c
@@ -5,10 +5,12 @@
 
 static int j;                   /* remaining bytes to copy */
 
+extern struct lha_opts opts;
+
 void
 decode_start(void)
 {
-    huf_decode_start();
+    huf_decode_start(opts.method);
     j = 0;
 }
 
index ad5dcac..b3c3352 100644 (file)
--- a/encode.c
+++ b/encode.c
@@ -21,6 +21,8 @@ static uchar *level;
 static ushort *level;
 #endif
 
+extern struct lha_opts opts;
+
 static void
 allocate_memory(void)
 {
@@ -288,7 +290,7 @@ encode(void)
 
     allocate_memory();
     init_slide();
-    huf_encode_start();
+    huf_encode_start(opts.method);
     remainder = fread_crc(&text[DICSIZ], DICSIZ + MAXMATCH, infile);
 
     if (outfile != stdout && opts.quiet < 1) {
diff --git a/huf.c b/huf.c
index 3f0673b..d8c9eb7 100644 (file)
--- a/huf.c
+++ b/huf.c
@@ -20,6 +20,16 @@ static uint bufsiz = 0, blocksize;
 static ushort c_freq[2 * NC - 1], c_table[4096], c_code[NC],
     p_freq[2 * NP - 1], pt_table[256], pt_code[NPT], t_freq[2 * NT - 1];
 
+static int np;
+static int pbit;
+
+static void
+init_parameter(struct lha_method *m)
+{
+    np   = m->dicbit + 1;
+    pbit = m->pbit;
+}
+
 /***** encoding *****/
 
 static void
@@ -169,13 +179,13 @@ send_block(void)
         putbits(CBIT, 0);
         putbits(CBIT, root);
     }
-    root = make_tree(NP, p_freq, pt_len, pt_code);
-    if (root >= NP) {
-        write_pt_len(NP, PBIT, -1);
+    root = make_tree(np, p_freq, pt_len, pt_code);
+    if (root >= np) {
+        write_pt_len(np, pbit, -1);
     }
     else {
-        putbits(PBIT, 0);
-        putbits(PBIT, root);
+        putbits(pbit, 0);
+        putbits(pbit, root);
     }
     pos = 0;
     for (i = 0; i < size; i++) {
@@ -196,7 +206,7 @@ send_block(void)
     }
     for (i = 0; i < NC; i++)
         c_freq[i] = 0;
-    for (i = 0; i < NP; i++)
+    for (i = 0; i < np; i++)
         p_freq[i] = 0;
 }
 
@@ -234,10 +244,12 @@ output(uint c, uint p)
 }
 
 void
-huf_encode_start(void)
+huf_encode_start(struct lha_method *m)
 {
     int i;
 
+    init_parameter(m);
+
     if (bufsiz == 0) {
         bufsiz = 16 * 1024U;
         while ((buf = malloc(bufsiz)) == NULL) {
@@ -249,7 +261,7 @@ huf_encode_start(void)
     buf[0] = 0;
     for (i = 0; i < NC; i++)
         c_freq[i] = 0;
-    for (i = 0; i < NP; i++)
+    for (i = 0; i < np; i++)
         p_freq[i] = 0;
     output_pos = output_mask = 0;
     init_putbits();
@@ -362,7 +374,7 @@ decode_c(void)
         blocksize = getbits(16);
         read_pt_len(NT, TBIT, 3);
         read_c_len();
-        read_pt_len(NP, PBIT, -1);
+        read_pt_len(np, pbit, -1);
     }
     blocksize--;
     j = c_table[bitbuf >> (BITBUFSIZ - 12)];
@@ -386,7 +398,7 @@ decode_p(void)
     uint j, mask;
 
     j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
-    if (j >= NP) {
+    if (j >= np) {
         mask = 1U << (BITBUFSIZ - 1 - 8);
         do {
             if (bitbuf & mask)
@@ -394,7 +406,7 @@ decode_p(void)
             else
                 j = left[j];
             mask >>= 1;
-        } while (j >= NP);
+        } while (j >= np);
     }
     fillbuf(pt_len[j]);
     if (j != 0)
@@ -403,8 +415,9 @@ decode_p(void)
 }
 
 void
-huf_decode_start(void)
+huf_decode_start(struct lha_method *m)
 {
+    init_parameter(m);
     init_getbits();
     blocksize = 0;
 }
index 5f59668..f618d39 100644 (file)
--- a/makefile
+++ b/makefile
@@ -10,7 +10,7 @@ $(TARGET): $(OBJS)
        $(CC) $(CFLAGS) -I. -c $<
 
 clean:
-       $(RM) $(OBJS) $(TARGET) $(TARGET).stackdump
+       $(RM) $(OBJS) $(TARGET) $(TARGET).stackdump tests/test.log
 
 check test: $(TARGET)
        sh ./tests/lha-test.sh 2
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644 (file)
index 0000000..c7ec943
--- /dev/null
@@ -0,0 +1 @@
+test.log
index 1769be0..fed2ca4 100644 (file)
@@ -22,20 +22,20 @@ $lha v test-tmp-m0.lzh | grep lh0
 #                                                      check $? $LINENO
 $lha v test-tmp-m5.lzh | grep lh5
                                                        check $? $LINENO
-$lha v test-tmp-m6.lzh | grep lh6
-#                                                      check $? $LINENO
-$lha v test-tmp-m7.lzh | grep lh7
-#                                                      check $? $LINENO
+$lha v test-tmp-m6.lzh | grep lh6
+                                                       check $? $LINENO
+$lha v test-tmp-m7.lzh | grep lh7
+                                                       check $? $LINENO
 $lha xw=test-tmp-m0 test-tmp-m0.lzh
                                                        check $? $LINENO
 # $lha xw=test-tmp-m1 test-tmp-m1.lzh
 #                                                      check $? $LINENO
 $lha xw=test-tmp-m5 test-tmp-m5.lzh
                                                        check $? $LINENO
-$lha xw=test-tmp-m6 test-tmp-m6.lzh
-#                                                      check $? $LINENO
-$lha xw=test-tmp-m7 test-tmp-m7.lzh
-#                                                      check $? $LINENO
+$lha xw=test-tmp-m6 test-tmp-m6.lzh
+                                                       check $? $LINENO
+$lha xw=test-tmp-m7 test-tmp-m7.lzh
+                                                       check $? $LINENO
 
 diff -r test-1 test-tmp-m0
                                                        check $? $LINENO
@@ -43,10 +43,10 @@ diff -r test-1 test-tmp-m0
 #                                                      check $? $LINENO
 diff -r test-1 test-tmp-m5
                                                        check $? $LINENO
-diff -r test-1 test-tmp-m6
-#                                                      check $? $LINENO
-diff -r test-1 test-tmp-m7
-#                                                      check $? $LINENO
+diff -r test-1 test-tmp-m6
+                                                       check $? $LINENO
+diff -r test-1 test-tmp-m7
+                                                       check $? $LINENO
 
 $lha pq test-tmp-m0.lzh test-a | diff test-a -
                                                        check $? $LINENO
@@ -54,10 +54,10 @@ $lha pq test-tmp-m0.lzh test-a | diff test-a -
 #                                                      check $? $LINENO
 $lha pq test-tmp-m5.lzh test-a | diff test-a -
                                                        check $? $LINENO
-$lha pq test-tmp-m6.lzh test-a | diff test-a -
-#                                                      check $? $LINENO
-$lha pq test-tmp-m7.lzh test-a | diff test-a -
-#                                                      check $? $LINENO
+$lha pq test-tmp-m6.lzh test-a | diff test-a -
+                                                       check $? $LINENO
+$lha pq test-tmp-m7.lzh test-a | diff test-a -
+                                                       check $? $LINENO
 
 cat test-[abc] > test-tmp-abc
 $lha pq test-tmp-m0.lzh | diff test-tmp-abc -
@@ -66,10 +66,10 @@ $lha pq test-tmp-m0.lzh | diff test-tmp-abc -
 #                                                      check $? $LINENO
 $lha pq test-tmp-m5.lzh | diff test-tmp-abc -
                                                        check $? $LINENO
-$lha pq test-tmp-m6.lzh | diff test-tmp-abc -
-#                                                      check $? $LINENO
-$lha pq test-tmp-m7.lzh | diff test-tmp-abc -
-#                                                      check $? $LINENO
+$lha pq test-tmp-m6.lzh | diff test-tmp-abc -
+                                                       check $? $LINENO
+$lha pq test-tmp-m7.lzh | diff test-tmp-abc -
+                                                       check $? $LINENO
 
 # empty file should be frozen with the -lh0- method.
 touch test-tmp-0byte