home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
F
/
LZHCPM.ARC
/
LHARC.C
next >
Wrap
Text File
|
2000-06-30
|
15KB
|
705 lines
static char *sccsid="@(#)LHARC.C version 1.13c 27/01/1990 by F. Duranti";
/*
* LHARC.C from LZHUFENC.C for adding members to an LHARC archive
* - (.LZH) files, v1.13 by Francesco Duranti 27/01/1990.
* LZHUFENC.C from LZHUF10.C for CPM, Eugene Nolan 4/13/89
* LZHUF.C English version 1.0 Based on Japanese version 29-NOV-1988
* LZSS coded by Haruhiko OKUMURA
* Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
* Edited and translated to English by Kenji RIKITAKE
*/
char *copyri="\nLHARC v1.13c by Francesco Duranti 27 January 1990\n\n";
#include "stdio.h"
#define TIME 0
#define DATE 0xBA91
int fnum,nfile,drv;
char files[128], arc_nam[128], fls[112][12], nome[112][13],
fcb[37], buffer[128], fcbnam[33], comp_type[6];
FILE *infile, *lharcf;
long int textsize, codesize, printcount;
struct archdr {
char hdr_len; /* header length in bytes */
char checksum; /* checksum of header only */
char stowage[5]; /* compression method- "-lh0-" or "-lh1-" */
long int comp_size; /* size of compressed file in bytes */
long int orig_size; /* size of the original file in bytes */
int file_time; /* file's last mod time, MS-DOS format */
int file_date; /* date, likewise */
int attrib; /* file's attributes, bit mapped */
char fn_len; /* #of characters in filename */
} archdr; /* (filename follows, variable length field) */
/* LZSS Parameters */
#define N 2048 /* Size of string buffer */
#define F 60 /* Size of look-ahead buffer */
#define THRESHOLD 2
#define NIL N /* End of tree's node */
char
text_buf[N + F - 1];
int m_position, m_length,
lson[N + 1], rson[N + 257], dad[N + 1];
void rewind(in)
FILE *in;
{
fseek(in,0L,0);
}
void errore(message, string)
char *message, *string;
{
fputs(message,stderr);
fputs(string,stderr);
fputs("\n",stderr);
exit(1);
}
void memmove(i,j,k)
char *i,*j;
int k;
{
while(k--) *j++ = *i++ ;
}
void strcpns(a,b)
char *a,*b;
{
char e;
do {
e=*a;
if (e!=' ') {
*b=e;
b++;
}
a++;
} while(e!='\0');
}
void InitTree() /* Initializing tree */
{
static unsigned i;
for (i = N + 1/* 4097*/; i <= N + 256/* 4352*/; i++)
rson[i] = NIL; /* root */
for (i = 0; i < N; i++)
dad[i] = NIL; /* node */
}
void InsertNode(r) int r; /* Inserting node to the tree */
{
static unsigned i;
static int p, cmp, rr;
static char *key;
static unsigned c;
rr=r;
cmp = 1;
key = &text_buf[rr];
p = N + 1 + key[0];
rson[rr] = lson[rr] = NIL;
m_length = 0;
for ( ; ; ) {
if (cmp >= 0) {
if (rson[p] != NIL)
p = rson[p];
else {
rson[p] = rr;
dad[rr] = p;
return;
}
} else {
if (lson[p] != NIL)
p = lson[p];
else {
lson[p] = rr;
dad[rr] = p;
return;
}
}
for (i = 1; i < F; i++)
if ((cmp = key[i] - text_buf[p + i]) != 0)
break;
if (i > THRESHOLD) {
if (i > m_length) {
m_position = ((rr - p) & (N - 1)/* 4095*/) - 1;
if ((m_length = i) >= F)
break;
}
if (i == m_length) {
if ((c = ((rr - p) & (N - 1)/* 4095*/) - 1) < m_position) {
m_position = c;
}
}
}
}
dad[rr] = dad[p];
lson[rr] = lson[p];
rson[rr] = rson[p];
dad[lson[p]] = dad[rson[p]] = rr;
/* dad[rson[p]] = r; */
if (rson[dad[p]] == p)
rson[dad[p]] = rr;
else
lson[dad[p]] = rr;
dad[p] = NIL; /* remove p */
}
void DeleteNode( p) int p; /* Deleting node from the tree */
{
static int q,pp;
pp=p;
if (dad[pp] == NIL)
return; /* unregistered */
if (rson[pp] == NIL)
q = lson[pp];
else
if (lson[pp] == NIL)
q = rson[pp];
else {
q = lson[pp];
if (rson[q] != NIL) {
do {
q = rson[q];
} while (rson[q] != NIL);
rson[dad[q]] = lson[q];
dad[lson[q]] = dad[q];
lson[q] = lson[pp];
dad[lson[pp]] = q;
}
rson[q] = rson[pp];
dad[rson[pp]] = q;
}
dad[q] = dad[pp];
if (rson[dad[pp]] == pp)
rson[dad[pp]] = q;
else
lson[dad[pp]] = q;
dad[pp] = NIL;
}
/* Huffman coding parameters */
/*#define N_CHAR (256 - THRESHOLD + F)*/
#define N_CHAR 314
/* character code (= 0..N_CHAR-1) */
/*#define T (N_CHAR * 2 - 1)*/ /* Size of table */
#define T 627
/*#define R (T - 1) */ /* root position */
#define R 626
#define MAX_FREQ 0x8000
/* update when cumulative frequency */
/* reaches to this value */
typedef char uchar;
/*
* Tables for encoding/decoding upper 6 bits of
* sliding dictionary pointer
*/
/* encoder table */
uchar p_len[64] = {
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
uchar p_code[64] = {
0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
unsigned freq[T + 1]; /* cumulative freq table */
/*
* pointing parent nodes.
* area [T..(T + N_CHAR - 1)] are pointers for leaves
*/
int prnt[T + N_CHAR];
/* pointing children nodes (son[], son[] + 1)*/
int son[T];
unsigned putbuf;
uchar putlen;
void Putcode(l, c) int l; unsigned c; /* output c bits */
{
putbuf |= c >> putlen;
if ((putlen += l) >= 8) {
putc(putbuf >> 8, lharcf/*outfile*/);
if ((putlen -= 8) >= 8) {
putc(putbuf, lharcf /*outfile*/);
codesize += 2;
putlen -= 8;
putbuf = c << (l - putlen);
} else {
putbuf <<= 8;
codesize++;
}
}
}
/* initialize freq tree */
void StartHuff()
{
static unsigned i, j;
for (i = 0; i < N_CHAR; i++) {
freq[i] = 1;
son[i] = i + T;
prnt[i + T] = i;
}
i = 0; j = N_CHAR;
while (j <= R) {
freq[j] = freq[i] + freq[i + 1];
son[j] = i;
prnt[i] = prnt[i + 1] = j;
i += 2; j++;
}
freq[T] = 0xffff;
prnt[R] = 0;
}
/* reconstruct freq tree */
void reconst()
{
static int i, j, k;
static unsigned f, l;
/* halven cumulative freq for leaf nodes */
j = 0;
for (i = 0; i < T; i++) {
if (son[i] >= T) {
freq[j] = (freq[i] + 1) / 2;
son[j] = son[i];
j++;
}
}
/* make a tree : first, connect children nodes */
for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
k = i + 1;
f = freq[j] = freq[i] + freq[k];
for (k = j - 1; f < freq[k]; k--);
k++;
l = (j - k) * 2;
/* movmem() is Turbo-C dependent
rewritten to memmove() by Kenji */
/* movmem(&freq[k], &freq[k + 1], l); */
memmove(&freq[k + 1], &freq[k], l);
freq[k] = f;
/* movmem(&son[k], &son[k + 1], l); */
memmove(&son[k + 1], &son[k], l);
son[k] = i;
}
/* connect parent nodes */
for (i = 0; i < T; i++) {
if ((k = son[i]) >= T) {
prnt[k] = i;
} else {
prnt[k] = prnt[k + 1] = i;
}
}
}
/* update freq tree */
void update( c) int c;
{
static int i, j, k, l, cc;
cc=c;
if (freq[R] == MAX_FREQ) {
reconst();
}
cc = prnt[cc + T];
do {
k = ++freq[cc];
/* swap nodes to keep the tree freq-ordered */
if (k > freq[l = cc + 1]) {
while (k > freq[++l]);
l--;
freq[cc] = freq[l];
freq[l] = k;
i = son[cc];
prnt[i] = l;
if (i < T) prnt[i + 1] = l;
j = son[l];
son[l] = i;
prnt[j] = cc;
if (j < T) prnt[j + 1] = cc;
son[cc] = j;
cc = l;
}
} while ((cc = prnt[cc]) != 0); /* do it until reaching the root */
}
unsigned code, len;
void EncChar( c) unsigned c;
{
static unsigned i;
static int j, k;
i = 0;
j = 0;
k = prnt[c + T];
/* search connections from leaf node to the root */
do {
i >>= 1;
/*
if node's address is odd, output 1
else output 0
*/
if (k & 1) i += 0x8000;
j++;
} while ((k = prnt[k]) != R);
Putcode(j, i);
code = i;
len = j;
update(c);
}
void EncPosition( c) unsigned c;
{
static unsigned i;
/* output upper 6 bits with encoding */
i = c >> 6;
Putcode(p_len[i], (unsigned)p_code[i] << 8);
/* output lower 6 bits directly */
Putcode(6, (c & 0x3f) << 10);
}
void EncEnd()
{
if (putlen) {
putc(putbuf >> 8, lharcf /*outfile*/);
codesize++;
}
}
/* Compression */
void Encode() /* Encoding/Compressing */
{
static int i, c, len, r, s, last_match_length;
rewind(infile);
StartHuff();
InitTree();
s = 0;
r = N - F;
for (i = s; i < r; i++)
text_buf[i] = ' ';
for (len = 0; len < F && (c = getc(infile)) != EOF; len++)
text_buf[r + len] = c;
textsize = len;
for (i = 1; i <= F; i++)
InsertNode(r - i);
InsertNode(r);
do {
if (m_length > len)
m_length = len;
if (m_length <= THRESHOLD) {
m_length = 1;
EncChar(text_buf[r]);
} else {
/* EncChar(255 - THRESHOLD + m_length); */
EncChar(253 + m_length);
EncPosition(m_position);
}
last_match_length = m_length;
for (i = 0; i < last_match_length &&
(c = getc(infile)) != EOF; i++) {
DeleteNode(s);
text_buf[s] = c;
if (s < F - 1)
text_buf[s + N] = c;
s = (s + 1) & (N - 1)/* 4095*/;
r = (r + 1) & (N - 1)/* 4095*/;
InsertNode(r);
}
textsize += i;
if ((textsize) > printcount) {
putc('o',stderr);
printcount += 1024;
}
while (i++ < last_match_length) {
DeleteNode(s);
s = (s + 1) & (N - 1) /*4095*/;
r = (r + 1) & (N - 1) /*4095*/;
if (--len) InsertNode(r);
}
} while (len > 0);
EncEnd();
}
void upper(c)
char *c;
{
for (;*c!='\0';c++) if (islower(*c)) *c=toupper(*c);
}
char mksum()
{
char *p, *q;
char i;
p = (char *)archdr.stowage;
q = p + sizeof (archdr)-2;
for (i = 0; p < q; p++) {
i += *p;
}
p = files;
q = p + archdr.fn_len;
for (; p < q; p++) {
i += *p;
}
return i;
}
void wrthdr1()
{
wrthdr(" ");
}
void wrthdr(stor)
char *stor;
{
archdr.fn_len=strlen(files);
archdr.hdr_len=sizeof(archdr)+archdr.fn_len-2;
strncpy(archdr.stowage,stor,5);
archdr.comp_size=codesize;
archdr.orig_size=textsize;
archdr.file_time=TIME;
archdr.file_date=DATE;
archdr.attrib=0x20; /* archivio MS-DOS non usato dal CP/M ed MSX-DOS */
archdr.checksum=mksum();
fwrite(&archdr.hdr_len,1,sizeof(archdr),lharcf);
fwrite(&files,1,archdr.fn_len,lharcf);
}
void copyfile()
{
long int i;
char chr;
rewind(infile);
for (i=0;i<textsize;i++) putc(getc(infile),lharcf);
}
int rdhdr()
{
char headln;
fread(&headln,1,1,lharcf);
if (headln=='\0') return NULL;
fread(&archdr.checksum,1,sizeof(archdr)-1,lharcf);
strncpy(comp_type, archdr.stowage, 5);
if ((strcmp(comp_type, "-lh1-") != 0) &&
(strcmp(comp_type, "-lh0-") != 0))
errore("Unsupported stowage method encountered.","\n");
return 1;
}
int readfn()
{
int j;
char nomef[15];
for (j=0;rdhdr()!=NULL;j++) {
fread(&nomef,1,archdr.fn_len,lharcf);
nomef[archdr.fn_len]='\0';
upper(nomef);
strcpy(nome[j],nomef);
fseek(lharcf,archdr.comp_size+(((archdr.hdr_len-archdr.fn_len)==22)?2:0),1);
}
return j;
}
void initfcb(fn)
char fn[];
{
int j,i;
fcb[0]=(char)drv;
for (j=1;j<12;j++) fcb[j]='?';
for (i=0,j=1;j<9;j++) {
if (fn[i]=='*') {
j=9;
while (fn[i]!='.') i++;
} else if (fn[i]=='.')
while(j<9) {
fcb[j]=' ';
j++;
}
else {
fcb[j]=fn[i];
i++;
}
}
for (i++,j=9;j<12;j++) {
if (fn[i]=='*') j=12;
else if (fn[i]==NULL)
while(j<12) {
fcb[j]=' ';
j++;
}
else {
fcb[j]=fn[i];
i++;
}
}
for (j=12;j<37;j++) fcb[j]=NULL;
}
void main(argc,argv)
int argc;
char *argv[];
{
int flag,c,q,i,j,ok;
long int len,pos1,pos2;
char n, inname[128], tempor[20], *tmpnam;
fputs(copyri,stderr);
if (argc>2) {
strcpy(arc_nam,argv[1]);
upper(arc_nam);
if (index(arc_nam, '.') == NULL)
strcat(arc_nam, ".LZH");
if ((lharcf=fopen(arc_nam,"r"))!=NULL) {
nfile=readfn();
len=ftell(lharcf)-1;
fclose(lharcf);
lharcf=fopen(arc_nam,"a");
fseek(lharcf,len,0);
} else {
if ((lharcf=fopen(arc_nam,"w"))==NULL)
errore("LHARC: can't create ",arc_nam);
nfile=0;
}
fprintf(stderr,"LHARC archive = %s\n",arc_nam);
for (q=2;q<argc;q++) {
strcpy(inname,argv[q]);
upper(inname);
if ((tmpnam=index(inname,':'))!=NULL) {
--tmpnam;
drv=(int)((*tmpnam)-64);
++tmpnam;
++tmpnam;
} else {
tmpnam=inname;
drv=bdos((char)0x19,0)+1;
}
if (index(inname, '.') == NULL)
strcat(inname, ".");
initfcb(tmpnam);
bdos((char)0x1a,buffer);
for (ok=bdos((char)0x11,fcb); ok!=0xff; ok=bdos((char)0x12,fcb)) {
memmove(buffer+ok*32,fcbnam,12);
if (fnum==0) {
memmove(fcbnam,fls[fnum],12);
fls[fnum][0]=(char)drv;
fnum++;
} else {
flag=1;
for (i=0;i<fnum;i++)
if (strncmp(&fls[i][1],&fcbnam[1],11)==0) flag=0;
if (flag==1) {
memmove(fcbnam,fls[fnum],12);
fls[fnum][0]=(char)drv;
fnum++;
}
}
}
}
for (i=0;i<fnum;i++) {
memmove(&fls[i][1],files,8);
files[8]='.';
memmove(&fls[i][9],&files[9],3);
files[12]=NULL;
inname[0]=(char)fls[i][0]+64;
inname[1]=':';
memmove(files,&inname[2],12);
inname[14]=NULL;
flag=1;
strcpns(files,tempor);
strcpy(files,tempor);
for (j=0;j<nfile;j++)
if (strcmp(nome[j],files)==0) flag=0;
if (flag!=0) {
if ((infile=fopen(inname,"r"))==NULL) {
fprintf(stderr,"\nLHARC: can't open %s\n",inname);
continue;
}
printcount=0;
fseek(infile, 0L, 2);
textsize = ftell(infile);
if (textsize!=0) {
fprintf(stderr,"Freezing %s :",inname);
j=(textsize+1023)/1024;
for(q=0;q<j;q++) putc('.',stderr);
for(q=0;q<j;q++) putc('\010',stderr);
textsize=codesize=printcount=0;
putlen=putbuf=0;
pos1=ftell(lharcf);
wrthdr1();
Encode();
pos2=ftell(lharcf);
fseek(lharcf,pos1,0);
if (codesize<textsize) {
wrthdr("-lh1-");
fseek(lharcf,pos2,0);
} else {
codesize=textsize;
wrthdr("-lh0-");
copyfile();
}
fclose(infile);
fprintf(stderr,"\rFrozen(%3.1f%%)\n",(double)codesize/textsize*100);
strcpy(nome[nfile],files);
++nfile;
} else fprintf(stderr,"%s is empty.\n",inname);
} else fprintf(stderr,"Skipping %s\n",inname);
}
putc('\0',lharcf);
fclose(lharcf);
} else {
fprintf(stderr,"Usage: LHARC [d:]<archive> [s:]<afn> ...\n\n");
fprintf(stderr,"where <archive> is an LHARC file (default .LZH).\n");
fprintf(stderr,"Files matching <afn> (wildcards allowed) are added to <archive>.\n");
fprintf(stderr,"You can also specify source [s:] and destination [d:] drive\n");
fprintf(stderr,"for all files.\n\n");
}
exit(0);
}
,"You can also specify source [s:] and destination [d:] drive\n");
fpr