lha_SOURCES = append.c bitio.c crcio.c dhuf.c extract.c header.c huf.c \
indicator.c larc.c lha.h lha_macro.h prototypes.h lhadd.c lharc.c \
lhext.c lhlist.c maketbl.c maketree.c patmatch.c shuf.c slide.c \
- util.c getopt_long.c getopt_long.h
+ util.c getopt_long.c getopt_long.h \
+ pm2.c pm2hist.c pm2hist.h pm2tree.c pm2tree.h
lha_LDADD = @LIBOBJS@
EXTRA_DIST = lhdir.h fnmatch.h
AM_CPPFLAGS=$(DEF_KCODE) $(SUPPORT_LZHUFF_METHOD)
case LARC4_METHOD_NUM: /* -lz4- */
interface.dicbit = LARC4_DICBIT;
break;
+ case PMARC0_METHOD_NUM: /* -pm0- */
+ interface.dicbit = PMARC0_DICBIT;
+ break;
+ case PMARC2_METHOD_NUM: /* -pm2- */
+ interface.dicbit = PMARC2_DICBIT;
+ break;
default:
warning("unknown method %d", method);
interface.dicbit = LZHUFF5_DICBIT; /* for backward compatibility */
break;
}
- if (interface.dicbit == 0) { /* LZHUFF0_DICBIT or LARC4_DICBIT */
+ if (interface.dicbit == 0) { /* LZHUFF0_DICBIT or LARC4_DICBIT or PMARC0_DICBIT*/
start_indicator(name,
original_size,
verify_mode ? "Testing " : "Melting ",
#define LARC5_METHOD "-lz5-"
#define LARC4_METHOD "-lz4-"
#define LZHDIRS_METHOD "-lhd-"
+#define PMARC0_METHOD "-pm0-"
+#define PMARC2_METHOD "-pm2-"
#define METHOD_TYPE_STORAGE 5
#define LARC5_METHOD_NUM 9
#define LARC4_METHOD_NUM 10
#define LZHDIRS_METHOD_NUM 11
+#define PMARC0_METHOD_NUM 12
+#define PMARC2_METHOD_NUM 13
/* Added N.Watazaki ..^ */
#define LZHUFF0_DICBIT 0 /* no compress */
#define LARC_DICBIT 11 /* 2^11 = 2KB sliding dictionary */
#define LARC5_DICBIT 12 /* 2^12 = 4KB sliding dictionary */
#define LARC4_DICBIT 0 /* no compress */
+#define PMARC0_DICBIT 0 /* no compress */
+#define PMARC2_DICBIT 13 /* 2^13 = 8KB sliding dictionary */
#ifdef SUPPORT_LH7
#define MAX_DICBIT LZHUFF7_DICBIT /* lh7 use 16bits */
LHa for UNIX V 1.00 Copyright(C) 1992 Masaru Oki\n\
LHa for UNIX V 1.14 Modified 1995 Nobutaka Watazaki\n\
LHa for UNIX V 1.14i Modified 2000 Tsugio Okamoto\n\
+LHA-PMA for UNIX V 2 PMA added 2000 Maarten ter Huurne\n\
Autoconfiscated 2001-2008 Koji Arai\n\
");
LZHUFF4_METHOD, LZHUFF5_METHOD, LZHUFF6_METHOD, LZHUFF7_METHOD,
LARC_METHOD, LARC5_METHOD, LARC4_METHOD,
LZHDIRS_METHOD,
+ PMARC0_METHOD, PMARC2_METHOD,
NULL
};
/* 1999.4.30 t.okamoto */
for (method = 0;; method++) {
if (methods[method] == NULL) {
- error("Unknown method \"%.*s\"; \"%s\" will be skiped ...",
+ error("Unknown method \"%.*s\"; \"%s\" will be skipped ...",
5, hdr->method, name);
return read_size;
}
--- /dev/null
+/***********************************************************
+ pm2.c -- extract pmext2 coding
+***********************************************************/
+#include <stdio.h>
+#include "lha.h"
+#include "pm2hist.h"
+#include "pm2tree.h"
+
+static unsigned long nextcount;
+static unsigned short lastupdate;
+
+/* repeated from slide.c */
+static unsigned short dicsiz1;
+#define offset (0x100 - 2)
+
+void decode_start_pm2(void)
+{
+ dicsiz1 = (1 << dicbit) - 1;
+ init_getbits();
+ hist_init();
+ nextcount = 0;
+ lastupdate = 0;
+ getbits(1); /* discard bit */
+}
+
+
+static unsigned char gettree1;
+
+static int historyBits[8] = { 3, 3, 4, 5, 5, 5, 6, 6 };
+static int historyBase[8] = { 0, 8, 16, 32, 64, 96, 128, 192 };
+static int repeatBits[6] = { 3, 3, 5, 6, 7, 0 };
+static int repeatBase[6] = { 17, 25, 33, 65, 129, 256 };
+
+unsigned short decode_c_pm2(void)
+{
+ /* various admin: */
+ while (lastupdate != loc)
+ {
+ hist_update(dtext[lastupdate]);
+ lastupdate = (lastupdate + 1) & dicsiz1;
+ }
+ while (decode_count >= nextcount)
+ /* Actually it will never loop, because count doesn't grow that fast.
+ However, this is the way LHA does it.
+ Probably other encoding methods can have repeats larger than 256 bytes.
+ Note: LHA puts this code in decode_p...
+ */
+ {
+ if (nextcount == 0x0000)
+ {
+ maketree1();
+ maketree2(5);
+ nextcount = 0x0400;
+ }
+ else if (nextcount == 0x0400)
+ {
+ maketree2(6);
+ nextcount = 0x0800;
+ }
+ else if (nextcount == 0x0800)
+ {
+ maketree2(7);
+ nextcount = 0x1000;
+ }
+ else if (nextcount == 0x1000)
+ {
+ if (getbits(1) != 0) maketree1();
+ maketree2(8);
+ nextcount = 0x2000;
+ }
+ else
+ { /* 0x2000, 0x3000, 0x4000, ... */
+ if (getbits(1) != 0)
+ {
+ maketree1();
+ maketree2(8);
+ }
+ nextcount += 0x1000;
+ }
+ }
+ gettree1 = tree_get(&tree1); /* value preserved for decode_p */
+
+ /* direct value (ret <= UCHAR_MAX) */
+ if (gettree1 < 8) return hist_lookup(
+ historyBase[gettree1] + getbits(historyBits[gettree1]) );
+ /* repeats: (ret > UCHAR_MAX) */
+ if (gettree1 < 23) return offset + 2 + (gettree1 - 8);
+ return offset + repeatBase[gettree1 - 23]
+ + getbits(repeatBits[gettree1 - 23]);
+}
+
+unsigned short decode_p_pm2(void)
+{
+ /* gettree1 value preserved from decode_c */
+ int nbits, delta, gettree2;
+ if (gettree1 == 8)
+ { /* 2-byte repeat with offset 0..63 */
+ nbits = 6; delta = 0;
+ }
+ else if (gettree1 < 28)
+ { /* n-byte repeat with offset 0..8191 */
+ gettree2 = tree_get(&tree2);
+ if (gettree2 == 0)
+ {
+ nbits = 6; delta = 0;
+ }
+ else
+ { /* 1..7 */
+ nbits = 5 + gettree2; delta = 1 << nbits;
+ }
+ }
+ else
+ { /* 256 bytes repeat with offset 0 */
+ nbits = 0; delta = 0;
+ }
+ return delta + getbits(nbits);
+
+}
--- /dev/null
+/***********************************************************
+ pm2hist.c -- history for pmext2 decoding
+***********************************************************/
+
+/* Circular double-linked list. */
+
+static unsigned char prev[0x100];
+static unsigned char next[0x100];
+static unsigned char lastbyte;
+
+void hist_init()
+{
+ int i;
+ for (i = 0; i < 0x100; i++)
+ {
+ prev[(0xFF + i) & 0xFF] = i;
+ next[(0x01 + i) & 0xFF] = i;
+ }
+ prev[0x7F] = 0x00; next[0x00] = 0x7F;
+ prev[0xDF] = 0x80; next[0x80] = 0xDF;
+ prev[0x9F] = 0xE0; next[0xE0] = 0x9F;
+ prev[0x1F] = 0xA0; next[0xA0] = 0x1F;
+ prev[0xFF] = 0x20; next[0x20] = 0xFF;
+ lastbyte = 0x20;
+}
+
+unsigned char hist_lookup(int n)
+{
+ int i;
+ unsigned char *direction = prev;
+ if (n >= 0x80)
+ {
+ /* Speedup: If you have to process more than half the ring,
+ it's faster to walk the other way around.
+ */
+ direction = next;
+ n = 0x100 - n;
+ }
+ for (i = lastbyte; n != 0; n--) i = direction[i];
+ return i;
+}
+
+void hist_update(unsigned char data)
+{
+ unsigned char oldNext, oldPrev, newNext;
+ if (data == lastbyte) return;
+
+ /* detach from old position */
+ oldNext = next[data];
+ oldPrev = prev[data];
+ prev[oldNext] = oldPrev;
+ next[oldPrev] = oldNext;
+
+ /* attach to new next */
+ newNext = next[lastbyte];
+ prev[newNext] = data;
+ next[data] = newNext;
+
+ /* attach to new prev */
+ prev[data] = lastbyte;
+ next[lastbyte] = data;
+
+ lastbyte = data;
+}
+
--- /dev/null
+/***********************************************************
+ pm2hist.h -- history for pmext2 decoding
+***********************************************************/
+
+/* Circular double-linked list. */
+
+void hist_init();
+unsigned char hist_lookup(int n);
+void hist_update(unsigned char data);
--- /dev/null
+/***********************************************************
+ pm2tree.c -- tree for pmext2 decoding
+***********************************************************/
+
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+#include "pm2tree.h"
+#include "lha.h"
+
+static unsigned char tree1left[32];
+static unsigned char tree1right[32];
+struct tree tree1 = { 0, tree1left, tree1right };
+static unsigned char table1[32];
+
+static unsigned char tree2left[8];
+static unsigned char tree2right[8];
+struct tree tree2 = { 0, tree2left, tree2right };
+static unsigned char table2[8];
+
+static unsigned char tree1bound;
+static unsigned char mindepth;
+
+void maketree1()
+{
+ int i, nbits, x;
+ tree1bound = getbits(5);
+ mindepth = getbits(3);
+ if (mindepth == 0)
+ {
+ tree_setsingle(&tree1, tree1bound - 1);
+ }
+ else
+ {
+ for (i = 0; i<32; i++) table1[i] = 0;
+ nbits = getbits(3);
+ for (i = 0; i < tree1bound; i++) {
+ x = getbits(nbits);
+ table1[i] = ( x == 0 ? 0 : x - 1 + mindepth );
+ }
+ tree_rebuild(&tree1, tree1bound, mindepth, table1);
+ }
+}
+
+void maketree2(int par_b) /* in use: 5 <= par_b <= 8 */
+{
+ int i, count, index;
+ if (tree1bound < 10) return;
+ if (tree1bound == 29 && mindepth == 0) return;
+
+ for (i = 0; i < 8; i++) table2[i] = 0;
+ for (i = 0; i < par_b; i++) table2[i] = getbits(3);
+ index = 0;
+ count = 0;
+ for (i = 0; i < 8; i++)
+ {
+ if (table2[i] != 0)
+ {
+ index = i;
+ count++;
+ }
+ }
+
+ if (count == 1)
+ {
+ tree_setsingle(&tree2, index);
+ }
+ else if (count > 1)
+ {
+ mindepth = 1;
+ tree_rebuild(&tree2, 8, mindepth, table2);
+ }
+ // Note: count == 0 is possible!
+ // Excluding that possibility was a bug in version 1.
+
+}
+
+int tree_get(struct tree *t)
+{
+ int i;
+ i = t->root;
+ while (i < 0x80)
+ {
+ i = ( getbits(1) == 0 ? t->leftarr[i] : t->rightarr[i] );
+ }
+ return i & 0x7F;
+}
+
+void tree_setsingle(struct tree *t, unsigned char value)
+{
+ t->root = 128 | value;
+}
+
+void tree_rebuild(t, bound, mindepth, table)
+struct tree *t;
+unsigned char bound;
+unsigned char mindepth;
+unsigned char *table;
+{
+ unsigned char *parentarr, d;
+ int i, curr, empty, n;
+ parentarr = (unsigned char *)malloc(bound * sizeof(unsigned char));
+ t->root = 0;
+ for (i = 0; i < bound; i++)
+ {
+ t->leftarr[i] = 0;
+ t->rightarr[i] = 0;
+ parentarr[i] = 0;
+ }
+
+ for (i = 0; i < mindepth - 1; i++)
+ {
+ t->leftarr[i] = i + 1;
+ parentarr[i+1] = i;
+ }
+
+ curr = mindepth - 1;
+ empty = mindepth;
+ for (d = mindepth; TRUE; d++)
+ {
+ for (i = 0; i < bound; i++)
+ {
+ if (table[i] == d)
+ {
+ if (t->leftarr[curr] == 0) t->leftarr[curr] = i | 128;
+ else
+ {
+ t->rightarr[curr] = i | 128;
+ n = 0;
+ while (t->rightarr[curr] != 0)
+ {
+ if (curr == 0) /* root? -> done */
+ {
+ free(parentarr);
+ return;
+ }
+ curr = parentarr[curr];
+ n++;
+ }
+ t->rightarr[curr] = empty;
+ for (;;)
+ {
+ parentarr[empty] = curr;
+ curr = empty;
+ empty++;
+
+ n--; if (n == 0) break;
+ t->leftarr[curr] = empty;
+ }
+ }
+ }
+ }
+ if (t->leftarr[curr] == 0) t->leftarr[curr] = empty; else t->rightarr[curr] = empty;
+
+ parentarr[empty] = curr;
+ curr = empty;
+ empty++;
+ }
+}
+
--- /dev/null
+/***********************************************************
+ pm2tree.h -- tree for pmext2 decoding
+***********************************************************/
+
+struct tree { unsigned char root, *leftarr, *rightarr; };
+
+extern struct tree tree1, tree2;
+
+void maketree1();
+void maketree2(int par_b);
+int tree_get(struct tree *t);
+void tree_setsingle(struct tree *t, unsigned char value);
+void tree_rebuild(struct tree *t, unsigned char bound,
+ unsigned char mindepth, unsigned char *table);
unsigned short decode_c_lz5 P_((void));
unsigned short decode_p_lz5 P_((void));
void decode_start_lz5 P_((void));
+/* pm2.c */
+unsigned short decode_c_pm2 P_((void));
+unsigned short decode_p_pm2 P_((void));
+void decode_start_pm2 P_((void));
/* lhadd.c */
FILE *append_it P_((char *name, FILE *oafp, FILE *nafp));
FILE *build_temporary_file P_((void));
/* lzs */
{decode_c_lzs, decode_p_lzs, decode_start_lzs},
/* lz5 */
- {decode_c_lz5, decode_p_lz5, decode_start_lz5}
+ {decode_c_lz5, decode_p_lz5, decode_start_lz5},
+ /* lz4 */
+ {NULL , NULL , NULL },
+ /* lhd */
+ {NULL , NULL , NULL },
+ /* pm0 */
+ {NULL , NULL , NULL },
+ /* pm2 */
+ {decode_c_pm2, decode_p_pm2, decode_start_pm2}
};
static struct encode_option encode_set;
decode_set.decode_start();
dicsiz1 = dicsiz - 1;
adjust = 256 - THRESHOLD;
- if (interface->method == LARC_METHOD_NUM)
+ if ((interface->method == LARC_METHOD_NUM) || (interface->method == PMARC2_METHOD_NUM))
adjust = 256 - 2;
decode_count = 0;