home *** CD-ROM | disk | FTP | other *** search
- 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