home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / System / XADmaster / xad_dev / Sources / clients / HA.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-01  |  30.6 KB  |  1,241 lines

  1. #ifndef XADMASTER_HA_C
  2. #define XADMASTER_HA_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        HA.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: HA.c 1.1 (23.12.2000)
  9.     Author:        SDI
  10.     Distribution:    GPL
  11.     Description:    HA file archiver client
  12.  
  13.  1.0   05.11.00 : first version
  14.  1.1   23.12.00 : added missing TAG_DONE
  15. */
  16. #define DEBUG
  17.  
  18. #include <proto/xadmaster.h>
  19. #include <exec/memory.h>
  20. #include "SDI_compiler.h"
  21. #include "ConvertE.c"
  22. #include "xadCPU.h"
  23. #include "xadIO.c"
  24. #define SDI_TO_ANSI
  25. #include "SDI_ASM_STD_protos.h"
  26.  
  27. #ifndef XADMASTERFILE
  28. #define HA_Client        FirstClient
  29. #define NEXTCLIENT        0
  30. #define XADMASTERVERSION    9
  31. UBYTE version[] = "$VER: HA 1.1 (23.12.2000)" CPUTEXT " GPL by Dirk Stöcker";
  32. #endif
  33. #define HA_VERSION        1
  34. #define HA_REVISION        1
  35.  
  36. #define HATYPE_CPY    0
  37. #define HATYPE_ASC    1
  38. #define HATYPE_HSC    2
  39. #define HATYPE_DIR    14
  40. #define HATYPE_SPECIAL    15
  41.  
  42. #define HAMTYPE_MSDOS    1
  43. #define HAMTYPE_UNIX    2
  44.  
  45. #define HA_ISVTX     0x0200
  46. #define HA_ISGID     0x0400
  47. #define HA_ISUID     0x0800
  48.  
  49. #define HA_IRUSR     0x0100
  50. #define HA_IWUSR     0x0080 
  51. #define HA_IXUSR     0x0040
  52.  
  53. #define HA_IRGRP     0x0020
  54. #define HA_IWGRP     0x0010
  55. #define HA_IXGRP     0x0008
  56.  
  57. #define HA_IROTH     0x0004
  58. #define HA_IWOTH     0x0002
  59. #define HA_IXOTH     0x0001
  60.  
  61. #define HA_IFMT      0xf000
  62. #define HA_IFIFO     0x1000
  63. #define HA_IFCHR     0x2000
  64. #define HA_IFDIR     0x4000
  65. #define HA_IFBLK     0x6000
  66. #define HA_IFREG     0x8000
  67. #define HA_IFLNK     0xa000
  68. #define HA_IFSOCK    0xc000
  69.  
  70. #define HA_ISDIR(m)  ((m&HA_IFMT)==HA_IFDIR)
  71. #define HA_ISCHR(m)  ((m&HA_IFMT)==HA_IFCHR)
  72. #define HA_ISBLK(m)  ((m&HA_IFMT)==HA_IFBLK)
  73. #define HA_ISLNK(m)  ((m&HA_IFMT)==HA_IFLNK)
  74. #define HA_ISFIFO(m) ((m&HA_IFMT)==HA_IFIFO)
  75. #define HA_ISSOCK(m) ((m&HA_IFMT)==HA_IFSOCK)
  76.  
  77. struct HAPrivate {
  78.   ULONG CRC32;
  79.   UBYTE Method;
  80. };
  81.  
  82. #define HAPI(a)    ((struct HAPrivate *) ((a)->xfi_PrivateInfo))
  83. #define HASCANSIZE    2048
  84.  
  85. static const STRPTR hatypes[] = {"CPY", "ASC", "HSC"};
  86.  
  87. /*
  88.   archive header (intel storage):
  89.   UBYTE[2]    ID = 'HA'
  90.   UWORD        number of entries
  91.  
  92.   file header:
  93.   UBYTE        (version<<4) + compression type
  94.   ULONG        Compressed file size
  95.   ULONG        Original file size
  96.   ULONG        CRC32
  97.   ULONG        timestamp (unix)
  98.   UBYTE[..]    pathname, filename
  99.   UBYTE        Length of machine specific information
  100.   UBYTE[..]    Machine specific information
  101. */
  102.  
  103. ASM(BOOL) HA_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *data),
  104. REG(a6, struct xadMasterBase *xadMasterBase))
  105. { CPUCHECK
  106.   if(data[0] == 'H' && data[1] == 'A' && (data[4]>>4) == 2 &&
  107.   (data[4]&0xF) <= HATYPE_SPECIAL && EndGetI32(data+5) <= 
  108.   EndGetI32(data+9))
  109.     return 1;
  110.   return 0;
  111. }
  112.  
  113. ASM(LONG) HA_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  114. REG(a6, struct xadMasterBase *xadMasterBase))
  115. {
  116.   LONG err, s, i, nsize, psize, msize;
  117.   ULONG num = 1;
  118.   struct xadFileInfo *fi = 0, *fi2;
  119.   STRPTR hdr, machine;
  120.  
  121.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, 4, 0, ai)))
  122.   {
  123.     if((hdr = xadAllocVec(HASCANSIZE, MEMF_PUBLIC)))
  124.     {
  125.       while(ai->xai_InPos < ai->xai_InSize && !err)
  126.       {
  127.         if((s = ai->xai_InSize - ai->xai_InPos) > HASCANSIZE)
  128.           s = HASCANSIZE;
  129.         if(!(err = xadHookAccess(XADAC_READ, s, hdr, ai)))
  130.         {
  131.           msize = 0;
  132.           for(psize = 0; psize <= s-20 && hdr[17+psize]; ++psize)
  133.             ;
  134.           for(nsize = 0; nsize+psize <= s-20 && hdr[17+psize+1+nsize]; ++nsize)
  135.             ;
  136.           if(nsize+psize <= s-20)
  137.             msize = hdr[17+psize+1+nsize+1];
  138.       if(hdr[0] >> 4 == 2 && (hdr[0]&0xF) <= HATYPE_SPECIAL &&
  139.       EndGetI32(hdr+1) <= EndGetI32(hdr+5) && psize + nsize + msize <= s-20)
  140.       {
  141.         machine = hdr+20+psize+nsize;
  142.  
  143.         if((hdr[0]&0xF) == HATYPE_SPECIAL)
  144.         {
  145.           if(machine[0] == HAMTYPE_UNIX && (machine[2]>>4) == 0xA) /* check fo link */
  146.           {
  147.             if((fi2 = xadAllocObject(XADOBJ_FILEINFO, XAD_OBJNAMESIZE, nsize+1+psize+1+EndGetI32(hdr+1)+1, TAG_DONE)))
  148.             {
  149.               i = 0;
  150.               if(psize)
  151.               {
  152.             for(i = 0; i < psize; ++i)
  153.             {
  154.               fi2->xfi_FileName[i] = hdr[17+i] == 0xFF ? '/' : hdr[17+i];
  155.                 }
  156.                 if(fi2->xfi_FileName[i-1] != '/')
  157.                   fi2->xfi_FileName[i++] = '/';
  158.               }
  159.               xadCopyMem(hdr+17+psize+1, fi2->xfi_FileName+i, nsize+1); i += nsize+1;
  160.  
  161.               if(!(err = xadHookAccess(XADAC_INPUTSEEK, 20+nsize+psize+msize-s, 0, ai)))
  162.               {
  163.                 fi2->xfi_LinkName = fi2->xfi_FileName+i;
  164.                 err = xadHookAccess(XADAC_READ, EndGetI32(hdr+1), fi2->xfi_LinkName, ai);
  165.             for(i = 0; fi2->xfi_LinkName[i]; ++i)
  166.             {
  167.               if(fi2->xfi_LinkName[i] == 0xFF)
  168.                 fi2->xfi_LinkName[i] = '/';
  169.             }
  170.               }
  171.               
  172.                   fi2->xfi_EntryNumber = num++;
  173.  
  174.                   xadConvertProtection(XAD_PROTUNIX, EndGetI16(machine+1), XAD_GETPROTAMIGA, &fi2->xfi_Protection, TAG_DONE);
  175.  
  176.               fi2->xfi_Flags |= XADFIF_LINK;
  177.                   xadConvertDates(XAD_DATEUNIX, EndGetI32(hdr+13), XAD_GETDATEXADDATE, &fi2->xfi_Date, TAG_DONE);
  178.  
  179.               if(!fi)
  180.                     ai->xai_FileInfo = fi2;
  181.                   else
  182.                     fi->xfi_Next = fi2;
  183.                   fi = fi2;
  184.             }
  185.             else
  186.               err = XADERR_NOMEMORY;
  187.           }
  188.           else
  189.             err = xadHookAccess(XADAC_INPUTSEEK, 20+nsize+psize+msize+EndGetI32(hdr+1)-s, 0, ai);
  190.         }
  191.         else if((fi2 = xadAllocObject(XADOBJ_FILEINFO, XAD_OBJNAMESIZE, nsize+1+psize+1,
  192.         XAD_OBJPRIVINFOSIZE, sizeof(struct HAPrivate), TAG_DONE)))
  193.         {
  194.           i = 0;
  195.           if(psize)
  196.           {
  197.         for(i = 0; i < psize; ++i)
  198.         {
  199.           fi2->xfi_FileName[i] = hdr[17+i] == 0xFF ? '/' : hdr[17+i];
  200.             }
  201.             if(fi2->xfi_FileName[i-1] != '/')
  202.               fi2->xfi_FileName[i++] = '/';
  203.           }
  204.           xadCopyMem(hdr+17+psize+1, fi2->xfi_FileName+i, nsize+1);
  205.  
  206.               fi2->xfi_EntryNumber = num++;
  207.               fi2->xfi_CrunchSize = EndGetI32(hdr+1);
  208.               fi2->xfi_Size = EndGetI32(hdr+5);
  209.  
  210.           switch(machine[0])
  211.           {
  212.           case HAMTYPE_MSDOS: xadConvertProtection(XAD_PROTMSDOS, machine[1],
  213.             XAD_GETPROTAMIGA, &fi2->xfi_Protection, TAG_DONE); break;
  214.           case HAMTYPE_UNIX: xadConvertProtection(XAD_PROTUNIX, EndGetI16(machine+1),
  215.             XAD_GETPROTAMIGA, &fi2->xfi_Protection, TAG_DONE);
  216.             break;
  217.           }
  218.  
  219.           fi2->xfi_Flags |= XADFIF_SEEKDATAPOS;
  220.           fi2->xfi_DataPos = ai->xai_InPos-s+20+nsize+psize+msize;
  221.  
  222.               xadConvertDates(XAD_DATEUNIX, EndGetI32(hdr+13), XAD_GETDATEXADDATE, &fi2->xfi_Date, TAG_DONE);
  223.  
  224.           HAPI(fi2)->CRC32 = EndGetI32(hdr+9);
  225.           HAPI(fi2)->Method = hdr[0]&15;
  226.           if(HAPI(fi2)->Method == HATYPE_DIR)
  227.             fi2->xfi_Flags |= XADFIF_DIRECTORY;
  228.           else if(HAPI(fi2)->Method <= HATYPE_HSC)
  229.             fi2->xfi_EntryInfo = hatypes[HAPI(fi2)->Method];
  230.           err = xadHookAccess(XADAC_INPUTSEEK, fi2->xfi_DataPos+fi2->xfi_CrunchSize-ai->xai_InPos, 0, ai);
  231.  
  232.           if(!fi)
  233.                 ai->xai_FileInfo = fi2;
  234.               else
  235.                 fi->xfi_Next = fi2;
  236.               fi = fi2;
  237.         }
  238.         else
  239.           err = XADERR_NOMEMORY;
  240.       }
  241.       else
  242.         err = XADERR_ILLEGALDATA;
  243.     }
  244.       }
  245.       xadFreeObjectA(hdr,0);
  246.     }
  247.     else
  248.       err = XADERR_NOMEMORY;
  249.  
  250.     if(!err && ai->xai_InPos < ai->xai_InSize)
  251.       err = XADERR_ILLEGALDATA;
  252.     if(err)
  253.     {
  254.       ai->xai_Flags |= XADAIF_FILECORRUPT;
  255.       ai->xai_LastError = err;
  256.     }
  257.   }
  258.   return (ai->xai_FileInfo ? 0 : err);
  259. }
  260.  
  261.  
  262. /* Arithmetic Decoding *******************************************************/
  263.  
  264. struct HaArithData {
  265.  struct xadInOut *io;
  266.  UWORD h;
  267.  UWORD l;
  268.  UWORD v;
  269.  WORD  s;
  270.  WORD  gpat;
  271.  WORD  ppat;
  272. };
  273.  
  274. static void HA_ac_init_decode(struct HaArithData *dat)
  275. {
  276.   dat->h = 0xffff;
  277. /*  dat->l = 0; */
  278. /*  dat->gpat = 0; */
  279.   dat->v = xadIOGetChar(dat->io)<<8;
  280.   dat->v |= 0xff&xadIOGetChar(dat->io);
  281. }
  282.  
  283. UWORD HA_ac_threshold_val(struct HaArithData *dat, UWORD tot)
  284. {
  285.   ULONG r;
  286.     
  287.   r = (ULONG)(dat->h - dat->l)+1;
  288.   return (UWORD)((((ULONG)(dat->v-dat->l)+1)*tot-1)/r);
  289. }
  290.  
  291. #define HA_getbit(b)     { dat->gpat <<= 1;                \
  292.               if(!(dat->gpat&0xff)) {            \
  293.                 dat->gpat=xadIOGetChar(dat->io);        \
  294.                 if(dat->gpat&0x100) dat->gpat=0x100;    \
  295.                 else {                    \
  296.                     dat->gpat <<= 1;        \
  297.                     dat->gpat |= 1;            \
  298.                 }                    \
  299.               }                        \
  300.               b |= (dat->gpat&0x100)>>8;            \
  301.             }
  302.  
  303. static void HA_ac_in(struct HaArithData *dat, UWORD low, UWORD high, UWORD tot)
  304. {
  305.   ULONG r;
  306.  
  307.   r = (ULONG)(dat->h - dat->l)+1;
  308.   dat->h = (UWORD)(r*high/tot-1)+dat->l;
  309.   dat->l += (UWORD)(r*low/tot);
  310.   while(!((dat->h^dat->l)&0x8000))
  311.   {
  312.     dat->l <<= 1;
  313.     dat->h <<= 1;
  314.     dat->h |= 1;
  315.     dat->v <<= 1;
  316.     HA_getbit(dat->v);
  317.   }
  318.   while((dat->l&0x4000)&&!(dat->h&0x4000))
  319.   {
  320.     dat->l <<= 1;
  321.     dat->l &= 0x7fff;
  322.     dat->h <<= 1;
  323.     dat->h |= 0x8001;
  324.     dat->v <<= 1;
  325.     dat->v ^= 0x8000;
  326.     HA_getbit(dat->v);
  327.   }
  328. }
  329.  
  330. /* ASC ***********************************************************************/
  331.  
  332. #define HA_POSCODES    31200
  333. #define HA_CTCODES    256
  334. #define HA_PTCODES    16
  335. #define HA_SLCODES    16
  336. #define HA_LLCODES    48
  337. #define HA_TTORD    4
  338. #define HA_LTSTEP    8
  339. #define HA_CTSTEP    1
  340. #define HA_TTSTEP    40
  341. #define HA_PTSTEP    24
  342. #define HA_MAXPT    (250*HA_PTSTEP)
  343. #define HA_MAXLT    (750*HA_LTSTEP)
  344. #define HA_MAXTT    (150*HA_TTSTEP)
  345. #define HA_MAXCT    (1000*HA_CTSTEP)
  346. #define HA_TTOMASK    (HA_TTORD-1);
  347. #define HA_LPLEN    4
  348. #define HA_CPLEN    8
  349. #define HA_LLLEN    16
  350. #define HA_LLBITS    4
  351. #define HA_CCUTOFF    (3*HA_CTSTEP)
  352. #define HA_LCUTOFF    (3*HA_LTSTEP)
  353. #define HA_LTCODES    (HA_SLCODES+HA_LLCODES)
  354. #define HA_LENCODES    (HA_SLCODES+HA_LLCODES*HA_LLLEN)
  355.  
  356. struct HaAscData {
  357.   struct HaArithData arith;
  358.   UWORD cblen;
  359.   UWORD bbf;
  360.   UWORD ccnt;
  361.   UWORD pmax;
  362.   UWORD npt;
  363.   UWORD ces;
  364.   UWORD les;
  365.   UWORD ttcon;
  366.   UWORD ltab[2*HA_LTCODES];
  367.   UWORD eltab[2*HA_LTCODES];
  368.   UWORD ptab[2*HA_PTCODES];
  369.   UWORD ctab[2*HA_CTCODES];
  370.   UWORD ectab[2*HA_CTCODES];
  371.   UWORD ttab[HA_TTORD][2];
  372.   UBYTE b[HA_POSCODES];
  373. };
  374.  
  375. static void HA_tabinit(UWORD *t, UWORD tl, UWORD ival)
  376. {
  377.   UWORD i,j;
  378.     
  379.   for(i = tl; i < 2*tl; ++i)
  380.     t[i] = ival;
  381.   for(i = tl-1, j = (tl<<1)-2; i; --i, j-=2)
  382.   {
  383.     t[i] = t[j] + t[j+1];
  384.   }
  385. }
  386.  
  387. static void HA_tscale(UWORD *t, UWORD tl)
  388. {
  389.   UWORD i,j;
  390.     
  391.   for(i = (tl<<1)-1; i>=tl; --i)
  392.   {
  393.     if(t[i]>1)
  394.       t[i]>>=1;
  395.   }
  396.   for(i = tl-1, j = (tl<<1)-2; i; --i, j-=2)
  397.   {
  398.     t[i] = t[j] + t[j+1];
  399.   }
  400. }
  401.  
  402. static void HA_ttscale(struct HaAscData *dat, UWORD con)
  403. {
  404.   dat->ttab[con][0]>>=1;
  405.   if(dat->ttab[con][0]==0)
  406.     dat->ttab[con][0]=1;
  407.   dat->ttab[con][1]>>=1;
  408.   if(dat->ttab[con][1]==0)
  409.     dat->ttab[con][1]=1;
  410. }
  411.  
  412. static void HA_tupd(UWORD *t, UWORD tl, UWORD maxt, UWORD step, UWORD p)
  413. {
  414.   WORD i;
  415.     
  416.   for(i = p+tl; i; i>>=1)
  417.     t[i] += step;
  418.   if(t[1] >= maxt)
  419.     HA_tscale(t,tl);
  420. }
  421.  
  422. static void HA_tzero(UWORD *t, UWORD tl, UWORD p)
  423. {
  424.   WORD i, step;
  425.     
  426.   for(i = p+tl, step = t[i]; i; i>>=1)
  427.     t[i] -= step;
  428. }
  429.  
  430. static LONG HA_asc(struct xadInOut *io)
  431. {
  432.   struct xadMasterBase *xadMasterBase = io->xio_xadMasterBase;
  433.   UWORD l,p,tv,i,lt;
  434.   struct HaAscData *dat;
  435.  
  436.   if((dat = (struct HaAscData *) xadAllocVec(sizeof(struct HaAscData), MEMF_PUBLIC|MEMF_CLEAR)))
  437.   {
  438.     dat->arith.io = io;
  439.     dat->cblen = HA_POSCODES;
  440.     dat->ces=HA_CTSTEP;
  441.     dat->les=HA_LTSTEP;
  442. /*    dat->ccnt=0; */
  443. /*    dat->ttcon=0; */
  444.     dat->npt = dat->pmax = 1;
  445.     for(i = 0; i < HA_TTORD; ++i)
  446.       dat->ttab[i][0] = dat->ttab[i][1] = HA_TTSTEP;
  447.     HA_tabinit(dat->ltab, HA_LTCODES,0);
  448.     HA_tabinit(dat->eltab,HA_LTCODES,1);
  449.     HA_tabinit(dat->ctab, HA_CTCODES,0);
  450.     HA_tabinit(dat->ectab,HA_CTCODES,1);
  451.     HA_tabinit(dat->ptab, HA_PTCODES,0);
  452.     HA_tupd(dat->ptab,HA_PTCODES,HA_MAXPT,HA_PTSTEP,0);
  453.  
  454.     HA_ac_init_decode(&dat->arith);
  455.     for(;;)
  456.     {
  457.       tv = HA_ac_threshold_val(&dat->arith, dat->ttab[dat->ttcon][0]+dat->ttab[dat->ttcon][1]+1);
  458.       i = dat->ttab[dat->ttcon][0]+dat->ttab[dat->ttcon][1];
  459.       if(dat->ttab[dat->ttcon][0] > tv)
  460.       {
  461.     HA_ac_in(&dat->arith, 0, dat->ttab[dat->ttcon][0], i+1);
  462.     dat->ttab[dat->ttcon][0] += HA_TTSTEP;
  463.  
  464.     if(i >= HA_MAXTT)
  465.       HA_ttscale(dat, dat->ttcon);
  466.  
  467.     dat->ttcon = (dat->ttcon<<1) & HA_TTOMASK;
  468.     tv = HA_ac_threshold_val(&dat->arith, dat->ctab[1] + dat->ces);
  469.  
  470.     if(tv >= dat->ctab[1])
  471.     {
  472.       HA_ac_in(&dat->arith, dat->ctab[1], dat->ctab[1]+dat->ces, dat->ctab[1]+dat->ces);
  473.       tv = HA_ac_threshold_val(&dat->arith, dat->ectab[1]);
  474.       for(l=2,lt=0;;)
  475.       {
  476.         if(lt+dat->ectab[l]<=tv)
  477.         {
  478.           lt += dat->ectab[l];
  479.           ++l;
  480.         }
  481.         if(l >= HA_CTCODES)
  482.         {
  483.           l -= HA_CTCODES;
  484.           break;
  485.         }
  486.         l <<= 1;
  487.       }
  488.       HA_ac_in(&dat->arith, lt,lt+dat->ectab[HA_CTCODES+l], dat->ectab[1]);
  489.       HA_tzero(dat->ectab, HA_CTCODES, l);
  490.       if(dat->ectab[1] != 0)
  491.         dat->ces += HA_CTSTEP;
  492.       else
  493.         dat->ces = 0;
  494.       for(i = l < HA_CPLEN ? 0 : l-HA_CPLEN; i < (l+HA_CPLEN >= HA_CTCODES-1 ? HA_CTCODES-1:l+HA_CPLEN); ++i)
  495.       {
  496.         if(dat->ectab[HA_CTCODES+i])
  497.           HA_tupd(dat->ectab, HA_CTCODES, HA_MAXCT, 1, i);
  498.       }
  499.     }
  500.     else
  501.     {
  502.       for(l=2,lt=0;;)
  503.       {
  504.         if(lt+dat->ctab[l] <= tv)
  505.         {
  506.           lt += dat->ctab[l];
  507.           l++;
  508.         }
  509.         if(l >= HA_CTCODES)
  510.         {
  511.           l -= HA_CTCODES;
  512.           break;
  513.         }
  514.         l <<= 1;
  515.       }
  516.       HA_ac_in(&dat->arith, lt, lt+dat->ctab[HA_CTCODES+l],dat->ctab[1]+dat->ces);
  517.     }
  518.  
  519.     HA_tupd(dat->ctab, HA_CTCODES, HA_MAXCT, HA_CTSTEP, l);
  520.     if(dat->ctab[HA_CTCODES+l] == HA_CCUTOFF)
  521.       dat->ces -= HA_CTSTEP < dat->ces ? HA_CTSTEP : dat->ces-1; 
  522.  
  523.     dat->b[dat->bbf] = xadIOPutChar(io, l);
  524.         if(++dat->bbf == dat->cblen)
  525.           dat->bbf=0;
  526.  
  527.     if(dat->ccnt < HA_POSCODES)
  528.       ++dat->ccnt;
  529.       }
  530.       else if (i > tv)
  531.       {
  532.     HA_ac_in(&dat->arith, dat->ttab[dat->ttcon][0],i,i+1);
  533.     dat->ttab[dat->ttcon][1] += HA_TTSTEP;
  534.     if(i >= HA_MAXTT)
  535.       HA_ttscale(dat, dat->ttcon);
  536.     dat->ttcon = ((dat->ttcon<<1)|1)&HA_TTOMASK;
  537.     while(dat->ccnt > dat->pmax)
  538.     {
  539.       HA_tupd(dat->ptab, HA_PTCODES, HA_MAXPT, HA_PTSTEP, dat->npt++);
  540.       dat->pmax <<= 1;    
  541.     }
  542.     tv = HA_ac_threshold_val(&dat->arith, dat->ptab[1]);
  543.     for(p=2,lt=0;;)
  544.     {
  545.       if(lt + dat->ptab[p] <= tv)
  546.       {
  547.         lt += dat->ptab[p];
  548.         p++;
  549.       }
  550.       if(p >= HA_PTCODES)
  551.       {
  552.         p -= HA_PTCODES;
  553.         break;
  554.       }
  555.       p <<= 1;
  556.     }
  557.     HA_ac_in(&dat->arith, lt, lt+dat->ptab[HA_PTCODES+p], dat->ptab[1]);
  558.     HA_tupd(dat->ptab, HA_PTCODES, HA_MAXPT, HA_PTSTEP, p);
  559.     if(p > 1)
  560.     {
  561.       for(i=1; p; i <<= 1)
  562.         --p;
  563.       i >>= 1;
  564.       if(i==(dat->pmax>>1))
  565.         l = dat->ccnt-(dat->pmax>>1);
  566.       else
  567.         l=i;
  568.       p = HA_ac_threshold_val(&dat->arith, l);
  569.       HA_ac_in(&dat->arith, p, p+1, l);
  570.       p += i;
  571.     }
  572.     tv = HA_ac_threshold_val(&dat->arith, dat->ltab[1]+dat->les);
  573.     if(tv >= dat->ltab[1])
  574.     {
  575.       HA_ac_in(&dat->arith, dat->ltab[1], dat->ltab[1]+dat->les, dat->ltab[1]+dat->les);
  576.       tv = HA_ac_threshold_val(&dat->arith, dat->eltab[1]);
  577.       for(l=2,lt=0;;)
  578.       {
  579.         if(lt+dat->eltab[l] <= tv)
  580.         {
  581.           lt += dat->eltab[l];
  582.           ++l;
  583.         }
  584.         if(l >= HA_LTCODES)
  585.         {
  586.           l -= HA_LTCODES;
  587.           break;
  588.         }
  589.         l <<= 1;
  590.       }
  591.       HA_ac_in(&dat->arith, lt, lt+dat->eltab[HA_LTCODES+l], dat->eltab[1]);
  592.       HA_tzero(dat->eltab, HA_LTCODES, l);
  593.       if(dat->eltab[1] != 0)
  594.         dat->les += HA_LTSTEP;
  595.       else
  596.         dat->les = 0;
  597.       for(i = l < HA_LPLEN ? 0 : l-HA_LPLEN; i<(l+HA_LPLEN >= HA_LTCODES-1 ? HA_LTCODES-1:l+HA_LPLEN);++i)
  598.       {
  599.         if(dat->eltab[HA_LTCODES+i])
  600.           HA_tupd(dat->eltab,HA_LTCODES,HA_MAXLT,1,i);
  601.       }
  602.     }
  603.     else
  604.     {
  605.       for(l=2,lt=0;;)
  606.       {
  607.         if(lt+dat->ltab[l] <= tv)
  608.         {
  609.           lt += dat->ltab[l];
  610.           ++l;
  611.         }
  612.         if(l >= HA_LTCODES)
  613.         {
  614.           l -= HA_LTCODES;
  615.           break;
  616.         }
  617.         l <<= 1;
  618.       }
  619.       HA_ac_in(&dat->arith, lt, lt+dat->ltab[HA_LTCODES+l], dat->ltab[1]+dat->les);
  620.     }
  621.     HA_tupd(dat->ltab, HA_LTCODES, HA_MAXLT, HA_LTSTEP, l);
  622.     if(dat->ltab[HA_LTCODES+l] == HA_LCUTOFF)
  623.       dat->les -= HA_LTSTEP < dat->les ? HA_LTSTEP : dat->les-1; 
  624.     if(l == HA_SLCODES-1)
  625.       l = HA_LENCODES-1;
  626.     else if(l >= HA_SLCODES)
  627.     {
  628.       i = HA_ac_threshold_val(&dat->arith, HA_LLLEN);
  629.       HA_ac_in(&dat->arith, i, i+1, HA_LLLEN);
  630.       l = ((l-HA_SLCODES) << HA_LLBITS)+i+HA_SLCODES-1;
  631.     }
  632.     l += 3;
  633.     if(dat->ccnt < HA_POSCODES)
  634.     {
  635.       dat->ccnt += l;
  636.       if(dat->ccnt > HA_POSCODES)
  637.         dat->ccnt = HA_POSCODES;
  638.     }
  639.         if(dat->bbf > p)
  640.           p = dat->bbf-1-p;
  641.         else
  642.           p=dat->cblen-1-p+dat->bbf;
  643.         while (l--)
  644.         {
  645.       dat->b[dat->bbf] = xadIOPutChar(io, dat->b[p]);
  646.       if(++dat->bbf == dat->cblen)
  647.         dat->bbf=0;
  648.       if(++p == dat->cblen)
  649.         p=0;
  650.         }
  651.       }
  652.       else
  653.       {
  654.     HA_ac_in(&dat->arith, i, i+1, i+1);
  655.         break;
  656.       }
  657.     }
  658.  
  659.     xadFreeObjectA(dat, 0);
  660.   }
  661.   return io->xio_Error;
  662. }
  663.  
  664. /* HSC ***********************************************************************/
  665.  
  666. #define HA_IECLIM    32    /* initial escape counter upper limit */
  667. #define HA_NECLIM    5    /* no escape expected counter limit */
  668. #define HA_NECTLIM    4
  669. #define HA_NECMAX    10    /* no escape expected counter maximum */
  670. #define HA_MAXCLEN    4    /* assumed to be 4 in several places */
  671. #define HA_NUMCON    10000    /* number of contexts to remember */ 
  672. #define HA_NUMCFB    32760    /* number of frequencies to remember */
  673. #define HA_ESCTH    3    /* threshold for escape calculation */
  674. #define HA_MAXTVAL    8000    /* maximum frequency value */
  675. #define HA_RFMINI    4    /* initial refresh counter value */
  676. #define HA_HTLEN    16384    /* length of hash table */
  677. #define HA_NIL        0xffff    /* NIL pointer in lists */
  678. #define HA_ESC        256    /* escape symbol */
  679.  
  680. struct HaHscData {
  681.   struct HaArithData arith;
  682.   UWORD usp;            /* stack pointer */
  683.   WORD  cslen;            /* length of context to search */
  684.   WORD  cmsp;            /* pointer to cmstack */
  685.   WORD  dropcnt;        /* counter for context len drop */
  686.   UWORD nrel;            /* context for frequency block release */
  687.   UWORD elf;            /* first of expire list */
  688.   UWORD    ell;            /* last of expire list */
  689.   UWORD fcfbl;            /* pointer to free frequency blocks */
  690.   UWORD elp[HA_NUMCON];        /* expire list previous pointer array */
  691.   UWORD eln[HA_NUMCON];        /* expire list next pointer array */
  692.   UWORD hrt[HA_HTLEN];        /* semi random data for hashing */
  693.   UWORD hs[HA_MAXCLEN+1];    /* hash stack for context search */ 
  694.   UWORD hp[HA_NUMCON];        /* hash list pointer array */
  695.   UWORD as[HA_MAXCLEN+1];    /* indexes to frequency array */
  696.   UWORD cps[HA_MAXCLEN+1];    /* context pointers */
  697.   UWORD nb[HA_NUMCFB];        /* next pointer for frequency array */
  698.   UWORD fa[HA_NUMCFB];        /* frequency array */
  699.   UWORD ft[HA_NUMCON];        /* total frequency of context */
  700.   UWORD ht[HA_HTLEN];        /* hash table */
  701.   UBYTE nec;            /* counter for no escape expected */
  702.   UBYTE maxclen;        /* current maximum length for context */ 
  703.   UBYTE curcon[4];        /* current context */
  704.   UBYTE cmask[256];        /* masked characters */
  705.   UBYTE cmstack[256];        /* stack of cmask[] entries to clear */ 
  706.   UBYTE cl[HA_NUMCON];        /* context length array */
  707.   UBYTE con[HA_NUMCON][4];    /* context array */
  708.   UBYTE fe[HA_NUMCON];        /* frequencys under ESCTH in context */
  709.   UBYTE fc[HA_NUMCFB];        /* character for frequency array */
  710.   UBYTE cc[HA_NUMCON];        /* character counts */
  711.   UBYTE rfm[HA_NUMCON];        /* refresh counter array */
  712.   UBYTE iec[HA_MAXCLEN+1];    /* initial escape counters */
  713. };
  714.  
  715. static UWORD HA_find_next(struct HaHscData *dat)
  716. {
  717.   WORD i,k;
  718.   UWORD cp;
  719.     
  720.   for(i = dat->cslen-1; i >= 0; --i)
  721.   {
  722.     k = dat->hs[i];
  723.     for(cp = dat->ht[k]; cp != HA_NIL; cp = dat->hp[cp])
  724.     {
  725.       if(dat->cl[cp] == i)
  726.       {
  727.     switch(i)
  728.     {
  729.     case 4: if(dat->curcon[3] != dat->con[cp][3]) break;
  730.         case 3: if(dat->curcon[2] != dat->con[cp][2]) break;
  731.         case 2: if(dat->curcon[1] != dat->con[cp][1]) break;
  732.         case 1: if(dat->curcon[0] != dat->con[cp][0]) break;
  733.         case 0: dat->cslen = i; return cp;
  734.     }
  735.       }    
  736.     }
  737.   }
  738.  
  739.   return HA_NIL;
  740. }
  741.  
  742. static UWORD HA_find_longest(struct HaHscData *dat)
  743. {
  744.   dat->hs[1] = dat->hrt[dat->curcon[0]];
  745.   dat->hs[2] = dat->hrt[(dat->curcon[1]+dat->hs[1])&(HA_HTLEN-1)];
  746.   dat->hs[3] = dat->hrt[(dat->curcon[2]+dat->hs[2])&(HA_HTLEN-1)];
  747.   dat->hs[4] = dat->hrt[(dat->curcon[3]+dat->hs[3])&(HA_HTLEN-1)];
  748.   dat->usp = 0;
  749.   while(dat->cmsp)
  750.     dat->cmask[dat->cmstack[--dat->cmsp]] = 0;
  751.   dat->cslen = HA_MAXCLEN+1;
  752.  
  753.   return HA_find_next(dat);
  754. }
  755.  
  756. static UWORD HA_adj_escape_prob(struct HaHscData *dat, UWORD esc, UWORD cp)
  757. {
  758.   if(dat->ft[cp] == 1)
  759.     return (UWORD) (dat->iec[dat->cl[cp]] >= (HA_IECLIM >> 1) ? 2 : 1);
  760.   if(dat->cc[cp] == 255)
  761.     return 1;
  762.   if(dat->cc[cp] && ((dat->cc[cp]+1) << 1) >= dat->ft[cp])
  763.   {
  764.     esc = (WORD)((LONG)esc*((dat->cc[cp]+1) << 1) / dat->ft[cp]);
  765.     if(dat->cc[cp] + 1 == dat->ft[cp])
  766.       esc += (dat->cc[cp]+1)>>1;
  767.   }
  768.   return (UWORD) (esc?esc:1);
  769. }
  770.  
  771. static WORD HA_decode_first(struct HaHscData *dat, UWORD cp)
  772. {
  773.   UWORD c, tv, i;
  774.   WORD sum,tot,esc,cf = 0;
  775.   UBYTE sv;
  776.  
  777.   esc = HA_adj_escape_prob(dat, dat->fe[cp], cp);
  778.   tot = dat->ft[cp];
  779.   if(dat->nec >= HA_NECLIM)
  780.   {
  781.     if(tot <= HA_NECTLIM && dat->nec == HA_NECMAX)
  782.       sv=2;
  783.     else
  784.       sv=1;
  785.     tot <<= sv;
  786.     tv = HA_ac_threshold_val(&dat->arith, tot+esc) >> sv;
  787.     for(c = cp, sum = 0; c != HA_NIL; c = dat->nb[c])
  788.     {
  789.       if(sum+dat->fa[c] <= tv)
  790.         sum += dat->fa[c];
  791.       else
  792.       {
  793.     cf = dat->fa[c] << sv;
  794.     break;
  795.       }
  796.     }
  797.     sum <<= sv;
  798.   }
  799.   else
  800.   {
  801.     tv = HA_ac_threshold_val(&dat->arith, tot+esc);
  802.     for(c = cp, sum = 0; c != HA_NIL; c = dat->nb[c])
  803.     {
  804.       if(sum+dat->fa[c] <= tv)
  805.         sum += dat->fa[c];
  806.       else
  807.       {
  808.     cf = dat->fa[c];
  809.     break;
  810.       }
  811.     }
  812.   }
  813.   dat->usp = 1;
  814.   if(c != HA_NIL)
  815.   {
  816.     HA_ac_in(&dat->arith, sum, sum+cf, tot+esc);
  817.     if(dat->ft[cp] == 1 && dat->iec[dat->cl[cp]])
  818.       --dat->iec[dat->cl[cp]];
  819.     dat->as[0] = c;
  820.     dat->cps[0] = cp;
  821.     c = dat->fc[c];
  822.     if(dat->nec < HA_NECMAX)
  823.       ++dat->nec;
  824.   }
  825.   else
  826.   {
  827.     HA_ac_in(&dat->arith, tot,tot+esc,tot+esc);
  828.     if(dat->ft[cp] == 1 && dat->iec[dat->cl[cp]] < HA_IECLIM)
  829.       ++dat->iec[dat->cl[cp]];
  830.     for(i = cp; i != HA_NIL; sum=i,i=dat->nb[i])
  831.     {
  832.       dat->cmstack[dat->cmsp++] = dat->fc[i];
  833.       dat->cmask[dat->fc[i]]=1;
  834.     }
  835.     dat->cps[0]=0x8000|cp;
  836.     dat->as[0]=sum;
  837.     c = HA_ESC;
  838.     dat->nec = 0;
  839.   }
  840.   return (WORD) c;
  841. }
  842.  
  843. static WORD HA_decode_rest(struct HaHscData *dat, UWORD cp)
  844. {
  845.   UWORD c, tv, i;
  846.   WORD sum,tot,esc,cf = 0;
  847.     
  848.   esc=tot=0;
  849.   for(i = cp; i != HA_NIL; i=dat->nb[i])
  850.   {
  851.     if(!dat->cmask[dat->fc[i]])
  852.     {
  853.       tot += dat->fa[i];
  854.       if(dat->fa[i] < HA_ESCTH)
  855.         ++esc;
  856.     }
  857.   }
  858.   esc = HA_adj_escape_prob(dat, esc, cp);
  859.   tv = HA_ac_threshold_val(&dat->arith, tot+esc);
  860.   for(c = cp, sum = 0; c != HA_NIL; c = dat->nb[c])
  861.   {
  862.     if(!dat->cmask[dat->fc[c]])
  863.     {
  864.       if(sum+dat->fa[c] <= tv)
  865.         sum += dat->fa[c];
  866.       else
  867.       {
  868.     cf = dat->fa[c];
  869.     break;
  870.       }
  871.     }
  872.   }
  873.   if(c != HA_NIL)
  874.   {
  875.     HA_ac_in(&dat->arith, sum,sum+cf,tot+esc);
  876.     if(dat->ft[cp]==1 && dat->iec[dat->cl[cp]])
  877.       --dat->iec[dat->cl[cp]];
  878.     dat->as[dat->usp] = c;
  879.     dat->cps[dat->usp++] = cp;
  880.     c = dat->fc[c];
  881.     ++dat->nec;
  882.   }
  883.   else
  884.   {
  885.     HA_ac_in(&dat->arith, tot,tot+esc,tot+esc);
  886.     if(dat->ft[cp] == 1 && dat->iec[dat->cl[cp]] < HA_IECLIM)
  887.       ++dat->iec[dat->cl[cp]];
  888.     for(i = cp; i != HA_NIL; sum=i,i=dat->nb[i])
  889.     {
  890.       if(!dat->cmask[dat->fc[i]])
  891.       {
  892.     dat->cmstack[dat->cmsp++] = dat->fc[i];
  893.     dat->cmask[dat->fc[i]] = 1;
  894.       }
  895.     }
  896.     dat->cps[dat->usp] = 0x8000|cp;
  897.     dat->as[dat->usp++]=sum;        /* sum holds last i !! */
  898.     c = HA_ESC;
  899.   }
  900.  
  901.   return (WORD) c;
  902. }
  903.  
  904. static WORD HA_decode_new(struct HaHscData *dat)
  905. {
  906.   WORD c;
  907.   UWORD tv,sum,tot;
  908.     
  909.   tot = 257 - dat->cmsp;
  910.   tv = HA_ac_threshold_val(&dat->arith, tot);
  911.   for(c = sum = 0; c < 256; ++c)
  912.   {
  913.     if(dat->cmask[c])
  914.       continue;
  915.     if(sum+1 <= tv)
  916.       ++sum;
  917.     else
  918.       break;
  919.   }
  920.   HA_ac_in(&dat->arith, sum, sum+1, tot);    
  921.   return c;
  922. }
  923.  
  924. static void HA_el_movefront(struct HaHscData *dat, UWORD cp)
  925. {
  926.   if(cp == dat->elf)
  927.     return;
  928.   if(cp == dat->ell)
  929.     dat->ell = dat->elp[cp];
  930.   else
  931.   {
  932.     dat->elp[dat->eln[cp]] = dat->elp[cp];
  933.     dat->eln[dat->elp[cp]] = dat->eln[cp];
  934.   }    
  935.   dat->elp[dat->elf] = cp;
  936.   dat->eln[cp] = dat->elf;
  937.   dat->elf = cp;
  938. }
  939.  
  940. static void HA_release_cfblocks(struct HaHscData *dat)
  941. {
  942.   UWORD i,j,d;
  943.     
  944.   do
  945.   {
  946.     do
  947.     {
  948.       if(++dat->nrel == HA_NUMCON)
  949.         dat->nrel = 0;
  950.     } while(dat->nb[dat->nrel] == HA_NIL);
  951.     for(i=0; i <= dat->usp; ++i)
  952.       if((dat->cps[i]&0x7fff) == dat->nrel)
  953.         break;
  954.   } while(i <= dat->usp);
  955.  
  956.   for(i = dat->nb[dat->nrel], d = dat->fa[dat->nrel]; i != HA_NIL; i = dat->nb[i])
  957.     if(dat->fa[i] < d)
  958.       d = dat->fa[i];
  959.   ++d;
  960.   if(dat->fa[dat->nrel] < d)
  961.   {
  962.     for(i = dat->nb[dat->nrel]; dat->fa[i] < d && dat->nb[i] != HA_NIL; i = dat->nb[i])
  963.       ;
  964.     dat->fa[dat->nrel] = dat->fa[i];
  965.     dat->fc[dat->nrel] = dat->fc[i];
  966.     j = dat->nb[i];
  967.     dat->nb[i] = dat->fcfbl;
  968.     dat->fcfbl = dat->nb[dat->nrel];
  969.     if((dat->nb[dat->nrel] = j) == HA_NIL)
  970.     {
  971.       dat->cc[dat->nrel] = 0;
  972.       dat->fe[dat->nrel] = (dat->ft[dat->nrel] = dat->fa[dat->nrel]) < HA_ESCTH ? 1 : 0;
  973.       return;
  974.     }
  975.   }
  976.   dat->fe[dat->nrel] = (dat->ft[dat->nrel] = dat->fa[dat->nrel] /= d) < HA_ESCTH ? 1 : 0;
  977.   dat->cc[dat->nrel] = 0;
  978.   for(j = dat->nrel, i = dat->nb[j]; i != HA_NIL;)
  979.   {
  980.     if(dat->fa[i] < d)
  981.     {
  982.       dat->nb[j] = dat->nb[i];
  983.       dat->nb[i] = dat->fcfbl;
  984.       dat->fcfbl = i;
  985.       i = dat->nb[j];
  986.     }
  987.     else
  988.     {
  989.        ++dat->cc[dat->nrel];
  990.        dat->ft[dat->nrel] += dat->fa[i] /= d;
  991.        if(dat->fa[i] < HA_ESCTH)
  992.          dat->fe[dat->nrel]++;
  993.        j=i;
  994.        i = dat->nb[i];
  995.     }
  996.   }
  997. }
  998.  
  999. static void HA_add_model(struct HaHscData *dat, WORD c)
  1000. {
  1001.   UWORD i;
  1002.   WORD cp;
  1003.     
  1004.   while(dat->usp != 0)
  1005.   {
  1006.     i = dat->as[--dat->usp];
  1007.     cp = dat->cps[dat->usp];
  1008.     if(cp&0x8000)
  1009.     {
  1010.       cp &= 0x7fff;
  1011.       if(dat->fcfbl == HA_NIL)
  1012.         HA_release_cfblocks(dat);
  1013.       dat->nb[i] = dat->fcfbl;
  1014.       i = dat->nb[i];
  1015.       dat->fcfbl = dat->nb[dat->fcfbl];
  1016.       dat->nb[i] = HA_NIL;
  1017.       dat->fa[i] = 1;
  1018.       dat->fc[i] = c;
  1019.       ++dat->cc[cp];
  1020.       ++dat->fe[cp];
  1021.     }
  1022.     else if(++dat->fa[i] == HA_ESCTH)
  1023.       --dat->fe[cp];
  1024.     if((dat->fa[i]<<1) < ++dat->ft[cp] / (dat->cc[cp]+1))
  1025.       --dat->rfm[cp];
  1026.     else if(dat->rfm[cp] < HA_RFMINI)
  1027.       ++dat->rfm[cp];
  1028.     if(!dat->rfm[cp] || dat->ft[cp] >= HA_MAXTVAL)
  1029.     {
  1030.       ++dat->rfm[cp];
  1031.       dat->fe[cp] = dat->ft[cp]=0;
  1032.       for(i = cp; i != HA_NIL; i = dat->nb[i])
  1033.       {
  1034.     if(dat->fa[i] > 1)
  1035.     {
  1036.       dat->ft[cp] += dat->fa[i] >>= 1;
  1037.       if(dat->fa[i] < HA_ESCTH)
  1038.         ++dat->fe[cp];
  1039.     }
  1040.     else
  1041.     {
  1042.       ++dat->ft[cp];
  1043.       ++dat->fe[cp];
  1044.     }
  1045.       }
  1046.     }
  1047.   }
  1048. }
  1049.  
  1050. #define HA_HASH(s,l,h)    { h = 0; if (l) h=dat->hrt[s[0]];             \
  1051.               if (l>1) h=dat->hrt[(s[1]+h)&(HA_HTLEN-1)]; \
  1052.               if (l>2) h=dat->hrt[(s[2]+h)&(HA_HTLEN-1)]; \
  1053.               if (l>3) h=dat->hrt[(s[3]+h)&(HA_HTLEN-1)];}
  1054.  
  1055. static UWORD HA_make_context(struct HaHscData *dat, UBYTE conlen, WORD c)
  1056. {
  1057.   WORD i;
  1058.   UWORD nc,fp;
  1059.     
  1060.   nc = dat->ell;
  1061.   dat->ell = dat->elp[nc];
  1062.   dat->elp[dat->elf] = nc;
  1063.   dat->eln[nc] = dat->elf;
  1064.   dat->elf = nc;
  1065.   if(dat->cl[nc] != 0xff)
  1066.   {
  1067.     if(dat->cl[nc] == HA_MAXCLEN && --dat->dropcnt==0)
  1068.       dat->maxclen = HA_MAXCLEN-1;
  1069.     HA_HASH(dat->con[nc], dat->cl[nc], i);
  1070.     if(dat->ht[i] == nc)
  1071.       dat->ht[i] = dat->hp[nc];
  1072.     else
  1073.     {
  1074.       for(i = dat->ht[i]; dat->hp[i] != nc; i = dat->hp[i])
  1075.         ;
  1076.       dat->hp[i] = dat->hp[nc];
  1077.     }
  1078.     if(dat->nb[nc] != HA_NIL)
  1079.     {
  1080.       for(fp = dat->nb[nc]; dat->nb[fp] != HA_NIL; fp = dat->nb[fp])
  1081.         ;
  1082.       dat->nb[fp] = dat->fcfbl;
  1083.       dat->fcfbl = dat->nb[nc];
  1084.     }
  1085.   }
  1086.   dat->nb[nc] = HA_NIL;
  1087.   dat->fe[nc] = dat->ft[nc] = dat->fa[nc] = 1;
  1088.   dat->fc[nc] = c;
  1089.   dat->rfm[nc] = HA_RFMINI;
  1090.   dat->cc[nc] = 0;
  1091.   dat->cl[nc] = conlen;
  1092.   dat->con[nc][0] = dat->curcon[0];
  1093.   dat->con[nc][1] = dat->curcon[1];
  1094.   dat->con[nc][2] = dat->curcon[2];
  1095.   dat->con[nc][3] = dat->curcon[3];
  1096.   HA_HASH(dat->curcon, conlen, i);
  1097.   dat->hp[nc] = dat->ht[i];
  1098.   dat->ht[i] = nc;
  1099.   return nc;
  1100. }
  1101.  
  1102. static LONG HA_hsc(struct xadInOut *io)
  1103. {
  1104.   struct xadMasterBase *xadMasterBase = io->xio_xadMasterBase;
  1105.   struct HaHscData *dat;
  1106.   WORD c = 0, i;
  1107.   UWORD cp;
  1108.   LONG z,h,l,t;
  1109.   UBYTE ncmax,ncmin;
  1110.  
  1111.   if((dat = (struct HaHscData *) xadAllocVec(sizeof(struct HaHscData), MEMF_PUBLIC|MEMF_CLEAR)))
  1112.   {
  1113.     dat->arith.io = io;
  1114.  
  1115.     dat->maxclen = HA_MAXCLEN;
  1116.     dat->iec[0] = (HA_IECLIM>>1);
  1117.     for(i=1; i <= HA_MAXCLEN; ++i)
  1118.       dat->iec[i] = (HA_IECLIM>>1)-1;
  1119.     dat->dropcnt = HA_NUMCON/4;
  1120. /*    nec=0; */
  1121. /*    nrel=0; */
  1122. /*    dat->hs[0] = 0; */
  1123.     for(i=0; i < HA_HTLEN; ++i)
  1124.       dat->ht[i] = HA_NIL;
  1125.     for(i=0; i < HA_NUMCON; ++i)
  1126.     {
  1127.       dat->eln[i] = i+1;
  1128.       dat->elp[i] = i-1;
  1129.       dat->cl[i] = 0xff;
  1130.       dat->nb[i] = HA_NIL;
  1131.     }
  1132. /*    dat->elf=0; */
  1133.     dat->ell = HA_NUMCON-1;
  1134.     for(i = HA_NUMCON; i < HA_NUMCFB-1; ++i)
  1135.       dat->nb[i] = i+1;
  1136.     dat->nb[i] = HA_NIL;
  1137.     dat->fcfbl = HA_NUMCON;
  1138. /*    dat->curcon[3] = dat->curcon[2] = dat->curcon[1] = dat->curcon[0] = 0; */
  1139. /*    dat->cmsp = 0; */
  1140. /*    for(i=0; i < 256; ++i) */
  1141. /*      dat->cmask[i] = 0; */
  1142.     for(z=10, i=0; i < HA_HTLEN; ++i)
  1143.     {
  1144.       h = z/(2147483647L/16807L);
  1145.       l = z%(2147483647L/16807L);
  1146.       if((t = 16807L*l-(2147483647L%16807L)*h)>0)
  1147.         z=t;
  1148.       else
  1149.         z=t+2147483647L;
  1150.       dat->hrt[i] = z&(HA_HTLEN-1);
  1151.     }
  1152.  
  1153.     HA_ac_init_decode(&dat->arith);
  1154.     while(c != HA_ESC)
  1155.     {
  1156.       cp = HA_find_longest(dat);
  1157.       ncmin = cp == HA_NIL ? 0 : dat->cl[cp]+1;
  1158.       ncmax = dat->maxclen+1;
  1159.       for(;;)
  1160.       {
  1161.     if(cp == HA_NIL)
  1162.     {
  1163.           c = HA_decode_new(dat);
  1164.       break;
  1165.         }            
  1166.     if((c = dat->cmsp ? HA_decode_rest(dat, cp) : HA_decode_first(dat, cp)) != HA_ESC)
  1167.     {
  1168.       HA_el_movefront(dat, cp);
  1169.       break;
  1170.         }        
  1171.         cp = HA_find_next(dat);
  1172.       }
  1173.       if(c != HA_ESC)
  1174.       {
  1175.         HA_add_model(dat, c);
  1176.         while(ncmax > ncmin)
  1177.           HA_make_context(dat, --ncmax, c);
  1178.         dat->curcon[3] = dat->curcon[2];
  1179.         dat->curcon[2] = dat->curcon[1];
  1180.     dat->curcon[1] = dat->curcon[0];
  1181.     dat->curcon[0] = c;
  1182.     xadIOPutChar(io, c);
  1183.       }
  1184.     }
  1185.  
  1186.     xadFreeObjectA(dat, 0);
  1187.   }
  1188.   return io->xio_Error;
  1189. }
  1190.  
  1191. /*****************************************************************************/
  1192.  
  1193. ASM(LONG) HA_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  1194. REG(a6, struct xadMasterBase *xadMasterBase))
  1195. {
  1196.   struct xadFileInfo *fi;
  1197.   struct xadInOut *io;
  1198.   LONG err;
  1199.  
  1200.   fi = ai->xai_CurFile;
  1201.  
  1202.   if((io = xadIOAlloc(XADIOF_ALLOCINBUFFER|XADIOF_ALLOCOUTBUFFER|XADIOF_NOCRC16|XADIOF_NOINENDERR, ai, xadMasterBase)))
  1203.   {
  1204.     io->xio_InSize = fi->xfi_CrunchSize;
  1205.     io->xio_OutSize = fi->xfi_Size;
  1206.     io->xio_CRC32 = ~0;
  1207.  
  1208.     switch(HAPI(fi)->Method)
  1209.     {
  1210.     case HATYPE_CPY:
  1211.       while(!(io->xio_Flags & (XADIOF_LASTOUTBYTE|XADIOF_ERROR)))
  1212.         xadIOPutChar(io, xadIOGetChar(io));
  1213.       err = io->xio_Error;
  1214.       break;
  1215.     case HATYPE_ASC: err = HA_asc(io); break;
  1216.     case HATYPE_HSC: err = HA_hsc(io); break;
  1217.     default: err = XADERR_DATAFORMAT;
  1218.     }
  1219.  
  1220.     if(!err)
  1221.       err = xadIOWriteBuf(io);
  1222.     if(!err && ~io->xio_CRC32 != HAPI(fi)->CRC32)
  1223.       err = XADERR_CHECKSUM;
  1224.     xadFreeObjectA(io, 0);
  1225.   }
  1226.   else
  1227.     err = XADERR_NOMEMORY;
  1228.  
  1229.   return err;
  1230. }
  1231.  
  1232. /*****************************************************************************/
  1233.  
  1234. const struct xadClient HA_Client = {
  1235. NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, HA_VERSION, HA_REVISION,
  1236. 22, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO, XADCID_HA, "HA",
  1237. (BOOL (*)()) HA_RecogData, (LONG (*)()) HA_GetInfo,
  1238. (LONG (*)()) HA_UnArchive, 0};
  1239.  
  1240. #endif /* XADMASTER_HA_C */
  1241.