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 >
Text File  |  2000-06-30  |  15KB  |  705 lines

  1. static char *sccsid="@(#)LHARC.C version 1.13c 27/01/1990 by F. Duranti";
  2. /*
  3.  * LHARC.C from LZHUFENC.C for adding members to an LHARC archive
  4.  *  - (.LZH) files, v1.13 by Francesco Duranti 27/01/1990.
  5.  * LZHUFENC.C from LZHUF10.C for CPM, Eugene Nolan 4/13/89
  6.  * LZHUF.C English version 1.0 Based on Japanese version 29-NOV-1988
  7.  * LZSS coded by Haruhiko OKUMURA
  8.  * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
  9.  * Edited and translated to English by Kenji RIKITAKE
  10.  */
  11.  
  12. char *copyri="\nLHARC   v1.13c  by Francesco Duranti  27 January 1990\n\n";
  13.  
  14. #include "stdio.h"
  15.  
  16. #define TIME 0
  17. #define DATE 0xBA91
  18.  
  19. int fnum,nfile,drv;
  20. char    files[128], arc_nam[128], fls[112][12], nome[112][13],
  21.     fcb[37], buffer[128], fcbnam[33], comp_type[6];
  22. FILE *infile, *lharcf;
  23. long int textsize, codesize, printcount;
  24.  
  25. struct archdr {
  26.     char        hdr_len;        /* header length in bytes */
  27.     char        checksum;        /* checksum of header only */
  28.     char        stowage[5];        /* compression method- "-lh0-" or "-lh1-" */
  29.     long int    comp_size;        /* size of compressed file in bytes */
  30.     long int    orig_size;        /* size of the original file in bytes */
  31.     int            file_time;        /* file's last mod time, MS-DOS format */
  32.     int            file_date;        /* date, likewise */
  33.     int            attrib;            /* file's attributes, bit mapped */
  34.     char        fn_len;            /* #of characters in filename */
  35. }        archdr;                    /* (filename follows, variable length field) */
  36.  
  37. /* LZSS Parameters */
  38.  
  39. #define N         2048    /* Size of string buffer */
  40. #define F         60      /* Size of look-ahead buffer */
  41. #define THRESHOLD       2
  42. #define NIL       N       /* End of tree's node  */
  43.  
  44. char
  45.         text_buf[N + F - 1];
  46. int       m_position, m_length,
  47.         lson[N + 1], rson[N + 257], dad[N + 1];
  48.  
  49. void rewind(in)
  50. FILE *in;
  51. {
  52.     fseek(in,0L,0);
  53. }
  54.  
  55. void errore(message, string)
  56. char *message, *string;
  57. {
  58.     fputs(message,stderr);
  59.     fputs(string,stderr);
  60.     fputs("\n",stderr);
  61.     exit(1);
  62. }
  63.  
  64. void memmove(i,j,k) 
  65. char *i,*j; 
  66. int k; 
  67. {
  68.     while(k--) *j++ = *i++ ;
  69. }
  70.  
  71. void strcpns(a,b)
  72. char *a,*b;
  73. {
  74.     char e;
  75.     do {
  76.         e=*a;
  77.         if (e!=' ') {
  78.             *b=e;
  79.             b++;
  80.         }
  81.         a++;
  82.     } while(e!='\0');
  83. }
  84.  
  85. void InitTree()  /* Initializing tree */
  86. {
  87. static  unsigned  i;
  88.  
  89.     for (i = N + 1/* 4097*/; i <= N + 256/* 4352*/; i++)
  90.         rson[i] = NIL;      /* root */
  91.     for (i = 0; i < N; i++)
  92.         dad[i] = NIL;     /* node */
  93. }
  94.  
  95. void InsertNode(r) int r;  /* Inserting node to the tree */
  96. {
  97. static  unsigned  i;
  98. static  int  p, cmp, rr;
  99. static  char  *key;
  100. static  unsigned c;
  101.     rr=r;
  102.     cmp = 1;
  103.     key = &text_buf[rr];
  104.     p = N + 1 + key[0];
  105.     rson[rr] = lson[rr] = NIL;
  106.     m_length = 0;
  107.     for ( ; ; ) {
  108.         if (cmp >= 0) {
  109.             if (rson[p] != NIL)
  110.                 p = rson[p];
  111.             else {
  112.                 rson[p] = rr;
  113.                 dad[rr] = p;
  114.                 return;
  115.             }
  116.         } else {
  117.             if (lson[p] != NIL)
  118.                 p = lson[p];
  119.             else {
  120.                 lson[p] = rr;
  121.                 dad[rr] = p;
  122.                 return;
  123.             }
  124.         }
  125.         for (i = 1; i < F; i++)
  126.             if ((cmp = key[i] - text_buf[p + i]) != 0)
  127.                 break;
  128.         if (i > THRESHOLD) {
  129.             if (i > m_length) {
  130.                 m_position = ((rr - p) & (N - 1)/* 4095*/) - 1;
  131.                 if ((m_length = i) >= F)
  132.                     break;
  133.             }
  134.             if (i == m_length) {
  135.              if ((c = ((rr - p) & (N - 1)/* 4095*/) - 1) < m_position) {
  136.                     m_position = c;
  137.                 }
  138.             }
  139.         }
  140.     }
  141.     dad[rr] = dad[p];
  142.     lson[rr] = lson[p];
  143.     rson[rr] = rson[p];
  144.     dad[lson[p]] = dad[rson[p]] = rr;
  145. /*      dad[rson[p]] = r; */
  146.     if (rson[dad[p]] == p)
  147.         rson[dad[p]] = rr;
  148.     else
  149.         lson[dad[p]] = rr;
  150.     dad[p] = NIL;  /* remove p */
  151. }
  152.  
  153. void DeleteNode( p) int p;  /* Deleting node from the tree */
  154. {
  155. static  int  q,pp;
  156.     pp=p;
  157.     if (dad[pp] == NIL)
  158.         return;   /* unregistered */
  159.     if (rson[pp] == NIL)
  160.         q = lson[pp];
  161.     else
  162.     if (lson[pp] == NIL)
  163.         q = rson[pp];
  164.     else {
  165.         q = lson[pp];
  166.         if (rson[q] != NIL) {
  167.             do {
  168.                 q = rson[q];
  169.             } while (rson[q] != NIL);
  170.             rson[dad[q]] = lson[q];
  171.             dad[lson[q]] = dad[q];
  172.             lson[q] = lson[pp];
  173.             dad[lson[pp]] = q;
  174.         }
  175.         rson[q] = rson[pp];
  176.         dad[rson[pp]] = q;
  177.     }
  178.     dad[q] = dad[pp];
  179.     if (rson[dad[pp]] == pp)
  180.         rson[dad[pp]] = q;
  181.     else
  182.         lson[dad[pp]] = q;
  183.     dad[pp] = NIL;
  184. }
  185.  
  186. /* Huffman coding parameters */
  187.  
  188. /*#define N_CHAR    (256 - THRESHOLD + F)*/
  189. #define N_CHAR 314
  190.                 /* character code (= 0..N_CHAR-1) */
  191. /*#define T       (N_CHAR * 2 - 1)*/ /* Size of table */
  192. #define T       627
  193. /*#define R       (T - 1) */      /* root position */
  194. #define R       626
  195. #define MAX_FREQ    0x8000
  196.                     /* update when cumulative frequency */
  197.                     /* reaches to this value */
  198.  
  199. typedef char uchar;
  200.  
  201. /*
  202.  * Tables for encoding/decoding upper 6 bits of
  203.  * sliding dictionary pointer
  204.  */
  205. /* encoder table */
  206. uchar p_len[64] = {
  207.     0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
  208.     0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
  209.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  210.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  211.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  212.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  213.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  214.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
  215. };
  216.  
  217. uchar p_code[64] = {
  218.     0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
  219.     0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
  220.     0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
  221.     0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
  222.     0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
  223.     0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
  224.     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  225.     0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
  226. };
  227.  
  228. unsigned freq[T + 1];   /* cumulative freq table */
  229.  
  230. /*
  231.  * pointing parent nodes.
  232.  * area [T..(T + N_CHAR - 1)] are pointers for leaves
  233.  */
  234. int prnt[T + N_CHAR];
  235.  
  236. /* pointing children nodes (son[], son[] + 1)*/
  237. int son[T];
  238.  
  239. unsigned putbuf;
  240. uchar putlen;
  241.  
  242. void Putcode(l,  c) int l; unsigned c;    /* output c bits */
  243. {
  244.     putbuf |= c >> putlen;
  245.     if ((putlen += l) >= 8) {
  246.         putc(putbuf >> 8, lharcf/*outfile*/);
  247.         if ((putlen -= 8) >= 8) {
  248.             putc(putbuf, lharcf /*outfile*/);
  249.             codesize += 2;
  250.             putlen -= 8;
  251.             putbuf = c << (l - putlen);
  252.         } else {
  253.             putbuf <<= 8;
  254.             codesize++;
  255.         }
  256.     }
  257. }
  258.  
  259.  
  260. /* initialize freq tree */
  261.  
  262. void StartHuff()
  263. {
  264. static  unsigned i, j;
  265.  
  266.     for (i = 0; i < N_CHAR; i++) {
  267.         freq[i] = 1;
  268.         son[i] = i + T;
  269.         prnt[i + T] = i;
  270.     }
  271.     i = 0; j = N_CHAR;
  272.     while (j <= R) {
  273.         freq[j] = freq[i] + freq[i + 1];
  274.         son[j] = i;
  275.         prnt[i] = prnt[i + 1] = j;
  276.         i += 2; j++;
  277.     }
  278.     freq[T] = 0xffff;
  279.     prnt[R] = 0;
  280. }
  281.  
  282.  
  283. /* reconstruct freq tree */
  284.  
  285. void reconst()
  286. {
  287. static  int i, j, k;
  288. static  unsigned f, l;
  289.  
  290.     /* halven cumulative freq for leaf nodes */
  291.     j = 0;
  292.     for (i = 0; i < T; i++) {
  293.         if (son[i] >= T) {
  294.             freq[j] = (freq[i] + 1) / 2;
  295.             son[j] = son[i];
  296.             j++;
  297.         }
  298.     }
  299.     /* make a tree : first, connect children nodes */
  300.     for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  301.         k = i + 1;
  302.         f = freq[j] = freq[i] + freq[k];
  303.         for (k = j - 1; f < freq[k]; k--);
  304.         k++;
  305.         l = (j - k) * 2;
  306.  
  307.         /* movmem() is Turbo-C dependent
  308.            rewritten to memmove() by Kenji */
  309.  
  310.         /* movmem(&freq[k], &freq[k + 1], l); */
  311.         memmove(&freq[k + 1], &freq[k], l);
  312.         freq[k] = f;
  313.         /* movmem(&son[k], &son[k + 1], l); */
  314.         memmove(&son[k + 1], &son[k], l);
  315.         son[k] = i;
  316.     }
  317.     /* connect parent nodes */
  318.     for (i = 0; i < T; i++) {
  319.         if ((k = son[i]) >= T) {
  320.             prnt[k] = i;
  321.         } else {
  322.             prnt[k] = prnt[k + 1] = i;
  323.         }
  324.     }
  325. }
  326.  
  327.  
  328. /* update freq tree */
  329.  
  330. void update( c) int c;
  331. {
  332. static  int i, j, k, l, cc;
  333.     cc=c;
  334.     if (freq[R] == MAX_FREQ) {
  335.         reconst();
  336.     }
  337.     cc = prnt[cc + T];
  338.     do {
  339.         k = ++freq[cc];
  340.  
  341.         /* swap nodes to keep the tree freq-ordered */
  342.         if (k > freq[l = cc + 1]) {
  343.             while (k > freq[++l]);
  344.             l--;
  345.             freq[cc] = freq[l];
  346.             freq[l] = k;
  347.  
  348.             i = son[cc];
  349.             prnt[i] = l;
  350.             if (i < T) prnt[i + 1] = l;
  351.  
  352.             j = son[l];
  353.             son[l] = i;
  354.  
  355.             prnt[j] = cc;
  356.             if (j < T) prnt[j + 1] = cc;
  357.             son[cc] = j;
  358.  
  359.             cc = l;
  360.         }
  361.     } while ((cc = prnt[cc]) != 0);   /* do it until reaching the root */
  362. }
  363.  
  364. unsigned code, len;
  365.  
  366. void EncChar( c) unsigned c;
  367. {
  368. static  unsigned i;
  369. static  int j, k;
  370.  
  371.     i = 0;
  372.     j = 0;
  373.     k = prnt[c + T];
  374.  
  375.     /* search connections from leaf node to the root */
  376.     do {
  377.         i >>= 1;
  378.  
  379.         /*
  380.         if node's address is odd, output 1
  381.         else output 0
  382.         */
  383.         if (k & 1) i += 0x8000;
  384.  
  385.         j++;
  386.     } while ((k = prnt[k]) != R);
  387.     Putcode(j, i);
  388.     code = i;
  389.     len = j;
  390.     update(c);
  391. }
  392.  
  393. void EncPosition( c) unsigned c;
  394. {
  395. static  unsigned i;
  396.  
  397.     /* output upper 6 bits with encoding */
  398.     i = c >> 6;
  399.     Putcode(p_len[i], (unsigned)p_code[i] << 8);
  400.  
  401.     /* output lower 6 bits directly */
  402.     Putcode(6, (c & 0x3f) << 10);
  403. }
  404.  
  405. void EncEnd()
  406. {
  407.     if (putlen) {
  408.         putc(putbuf >> 8, lharcf /*outfile*/);
  409.         codesize++;
  410.     }
  411. }
  412.  
  413. /* Compression */
  414.  
  415. void Encode()  /* Encoding/Compressing */
  416. {
  417. static  int  i, c, len, r, s, last_match_length;
  418.  
  419.     rewind(infile);
  420.     StartHuff();
  421.     InitTree();
  422.     s = 0;
  423.     r = N - F;
  424.     for (i = s; i < r; i++)
  425.         text_buf[i] = ' ';
  426.     for (len = 0; len < F && (c = getc(infile)) != EOF; len++)
  427.         text_buf[r + len] = c;
  428.     textsize = len;
  429.     for (i = 1; i <= F; i++)
  430.         InsertNode(r - i);
  431.     InsertNode(r);
  432.     do {
  433.         if (m_length > len)
  434.             m_length = len;
  435.         if (m_length <= THRESHOLD) {
  436.             m_length = 1;
  437.             EncChar(text_buf[r]);
  438.         } else {
  439. /*              EncChar(255 - THRESHOLD + m_length); */
  440.             EncChar(253 + m_length);
  441.             EncPosition(m_position);
  442.         }
  443.         last_match_length = m_length;
  444.         for (i = 0; i < last_match_length &&
  445.                 (c = getc(infile)) != EOF; i++) {
  446.             DeleteNode(s);
  447.             text_buf[s] = c;
  448.             if (s < F - 1)
  449.                 text_buf[s + N] = c;
  450.             s = (s + 1) & (N - 1)/* 4095*/;
  451.             r = (r + 1) & (N - 1)/* 4095*/;
  452.             InsertNode(r);
  453.         }
  454.         textsize += i;
  455.         if ((textsize) > printcount) {
  456.             putc('o',stderr);
  457.             printcount += 1024;
  458.         }
  459.         while (i++ < last_match_length) {
  460.             DeleteNode(s);
  461.             s = (s + 1) & (N - 1) /*4095*/;
  462.             r = (r + 1) & (N - 1) /*4095*/;
  463.             if (--len) InsertNode(r);
  464.         }
  465.     } while (len > 0);
  466.     EncEnd();
  467. }
  468.  
  469. void upper(c)
  470. char *c;
  471. {
  472.     for (;*c!='\0';c++) if (islower(*c)) *c=toupper(*c);
  473. }
  474.  
  475. char mksum()
  476. {
  477.     char *p, *q;
  478.     char i;
  479.     p = (char *)archdr.stowage;
  480.     q = p + sizeof (archdr)-2;
  481.     for (i = 0; p < q; p++) {
  482.         i += *p;
  483.     }
  484.     p = files;
  485.     q = p + archdr.fn_len;
  486.     for (; p < q; p++) {
  487.         i += *p;
  488.     }
  489.     return i;
  490. }
  491.  
  492. void wrthdr1()
  493. {
  494.     wrthdr("     ");
  495. }
  496.  
  497. void wrthdr(stor)
  498. char *stor;
  499. {
  500.     archdr.fn_len=strlen(files);
  501.     archdr.hdr_len=sizeof(archdr)+archdr.fn_len-2;
  502.     strncpy(archdr.stowage,stor,5);
  503.     archdr.comp_size=codesize;
  504.     archdr.orig_size=textsize;
  505.     archdr.file_time=TIME;
  506.     archdr.file_date=DATE;
  507.     archdr.attrib=0x20; /* archivio MS-DOS non usato dal CP/M ed MSX-DOS */
  508.     archdr.checksum=mksum();
  509.     fwrite(&archdr.hdr_len,1,sizeof(archdr),lharcf);
  510.     fwrite(&files,1,archdr.fn_len,lharcf);
  511. }
  512.  
  513.  
  514. void copyfile()
  515. {
  516.     long int i;
  517.     char chr;
  518.     rewind(infile);
  519.     for (i=0;i<textsize;i++) putc(getc(infile),lharcf);
  520. }
  521.  
  522.  
  523. int rdhdr()
  524. {
  525.     char headln;
  526.     fread(&headln,1,1,lharcf);
  527.     if (headln=='\0') return NULL;
  528.     fread(&archdr.checksum,1,sizeof(archdr)-1,lharcf);
  529.     strncpy(comp_type, archdr.stowage, 5);
  530.     if ((strcmp(comp_type, "-lh1-") != 0) &&
  531.         (strcmp(comp_type, "-lh0-") != 0))
  532.         errore("Unsupported stowage method encountered.","\n");
  533.     return 1;
  534. }
  535.  
  536. int readfn()
  537. {
  538.     int j;
  539.     char nomef[15];
  540.     for (j=0;rdhdr()!=NULL;j++) {
  541.         fread(&nomef,1,archdr.fn_len,lharcf);
  542.         nomef[archdr.fn_len]='\0';
  543.         upper(nomef);
  544.         strcpy(nome[j],nomef);
  545.         fseek(lharcf,archdr.comp_size+(((archdr.hdr_len-archdr.fn_len)==22)?2:0),1);
  546.         }
  547.     return j;
  548. }
  549.  
  550. void initfcb(fn)
  551. char fn[];
  552. {
  553.     int j,i;
  554.     fcb[0]=(char)drv;
  555.     for (j=1;j<12;j++) fcb[j]='?';
  556.     for (i=0,j=1;j<9;j++) {
  557.         if (fn[i]=='*') {
  558.             j=9;
  559.             while (fn[i]!='.') i++;
  560.         } else if (fn[i]=='.') 
  561.             while(j<9) {
  562.                 fcb[j]=' ';
  563.                 j++;
  564.             }
  565.         else {
  566.             fcb[j]=fn[i];
  567.             i++;
  568.         }
  569.     }
  570.     for (i++,j=9;j<12;j++) {
  571.         if (fn[i]=='*') j=12;
  572.         else if (fn[i]==NULL) 
  573.             while(j<12) {
  574.                 fcb[j]=' ';
  575.                 j++;
  576.             } 
  577.         else {
  578.             fcb[j]=fn[i];
  579.             i++;
  580.         }
  581.     }
  582.     for (j=12;j<37;j++) fcb[j]=NULL;
  583. }
  584.  
  585. void main(argc,argv)
  586. int argc;
  587. char *argv[];
  588. {
  589.     int flag,c,q,i,j,ok;
  590.     long int len,pos1,pos2;
  591.     char n, inname[128], tempor[20], *tmpnam;
  592.     fputs(copyri,stderr);
  593.     if (argc>2) {
  594.         strcpy(arc_nam,argv[1]);
  595.         upper(arc_nam);
  596.         if (index(arc_nam, '.') == NULL)
  597.             strcat(arc_nam, ".LZH");
  598.         if ((lharcf=fopen(arc_nam,"r"))!=NULL) {
  599.             nfile=readfn();
  600.             len=ftell(lharcf)-1;
  601.             fclose(lharcf);
  602.             lharcf=fopen(arc_nam,"a");
  603.             fseek(lharcf,len,0);
  604.         } else {
  605.             if ((lharcf=fopen(arc_nam,"w"))==NULL)
  606.                 errore("LHARC: can't create ",arc_nam);
  607.                 nfile=0;
  608.         }
  609.         fprintf(stderr,"LHARC archive = %s\n",arc_nam);
  610.         for (q=2;q<argc;q++) {
  611.             strcpy(inname,argv[q]);
  612.             upper(inname);
  613.             if ((tmpnam=index(inname,':'))!=NULL) {
  614.                 --tmpnam;
  615.                 drv=(int)((*tmpnam)-64);
  616.                 ++tmpnam;
  617.                 ++tmpnam;
  618.             } else {
  619.                 tmpnam=inname;
  620.                 drv=bdos((char)0x19,0)+1;
  621.             }
  622.             if (index(inname, '.') == NULL)
  623.             strcat(inname, ".");
  624.             initfcb(tmpnam);
  625.             bdos((char)0x1a,buffer);
  626.             for (ok=bdos((char)0x11,fcb); ok!=0xff; ok=bdos((char)0x12,fcb)) {
  627.                 memmove(buffer+ok*32,fcbnam,12);
  628.                 if (fnum==0) {
  629.                     memmove(fcbnam,fls[fnum],12);
  630.                     fls[fnum][0]=(char)drv;
  631.                     fnum++;
  632.                 } else {
  633.                     flag=1;
  634.                     for (i=0;i<fnum;i++)
  635.                         if (strncmp(&fls[i][1],&fcbnam[1],11)==0) flag=0;
  636.                     if (flag==1) {
  637.                         memmove(fcbnam,fls[fnum],12);
  638.                         fls[fnum][0]=(char)drv;
  639.                         fnum++;
  640.                     }
  641.                 }
  642.             }
  643.         }
  644.         for (i=0;i<fnum;i++) {
  645.             memmove(&fls[i][1],files,8);
  646.             files[8]='.';
  647.             memmove(&fls[i][9],&files[9],3);
  648.             files[12]=NULL;
  649.             inname[0]=(char)fls[i][0]+64;
  650.             inname[1]=':';
  651.             memmove(files,&inname[2],12);
  652.             inname[14]=NULL;
  653.             flag=1;
  654.             strcpns(files,tempor);
  655.             strcpy(files,tempor);
  656.             for (j=0;j<nfile;j++) 
  657.                 if (strcmp(nome[j],files)==0) flag=0;
  658.             if (flag!=0) {
  659.                 if ((infile=fopen(inname,"r"))==NULL) {
  660.                     fprintf(stderr,"\nLHARC: can't open %s\n",inname);
  661.                     continue;
  662.                 }
  663.                 printcount=0;
  664.                 fseek(infile, 0L, 2);
  665.                 textsize = ftell(infile);
  666.                 if (textsize!=0) {
  667.                     fprintf(stderr,"Freezing       %s :",inname);
  668.                     j=(textsize+1023)/1024;
  669.                     for(q=0;q<j;q++) putc('.',stderr);
  670.                     for(q=0;q<j;q++) putc('\010',stderr);
  671.                     textsize=codesize=printcount=0;
  672.                     putlen=putbuf=0;
  673.                     pos1=ftell(lharcf);
  674.                     wrthdr1();
  675.                     Encode();
  676.                     pos2=ftell(lharcf);
  677.                     fseek(lharcf,pos1,0);
  678.                     if (codesize<textsize) {
  679.                         wrthdr("-lh1-");
  680.                         fseek(lharcf,pos2,0);
  681.                     } else {
  682.                         codesize=textsize;
  683.                         wrthdr("-lh0-");
  684.                         copyfile();
  685.                     }
  686.                     fclose(infile);
  687.                     fprintf(stderr,"\rFrozen(%3.1f%%)\n",(double)codesize/textsize*100);
  688.                     strcpy(nome[nfile],files);
  689.                     ++nfile;
  690.                 } else fprintf(stderr,"%s is empty.\n",inname);
  691.             } else fprintf(stderr,"Skipping %s\n",inname);
  692.         }
  693.         putc('\0',lharcf);
  694.         fclose(lharcf);
  695.     } else {
  696.         fprintf(stderr,"Usage: LHARC [d:]<archive> [s:]<afn> ...\n\n");
  697.         fprintf(stderr,"where <archive> is an LHARC file (default .LZH).\n");
  698.         fprintf(stderr,"Files matching <afn> (wildcards allowed) are added to <archive>.\n");
  699.         fprintf(stderr,"You can also specify source [s:] and destination [d:] drive\n");
  700.         fprintf(stderr,"for all files.\n\n");
  701.     }
  702.     exit(0);
  703. }
  704. ,"You can also specify source [s:] and destination [d:] drive\n");
  705.         fpr