Logo Search packages:      
Sourcecode: fbb version File versions  Download package

lzhuf.c

   /****************************************************************
    Copyright (C) 1986-2000 by

    F6FBB - Jean-Paul ROUBELAT
    6, rue George Sand
    31120 - Roquettes - France
      jpr@f6fbb.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Parts of code have been taken from many other softwares.
    Thanks for the help.
    ****************************************************************/

/**************************************************************
                        lzhuf.c
                        written by Haruyasu Yoshizaki 11/20/1988
            some minor changes 4/6/1989
            comments translated by Haruhiko Okumura 4/7/1989
                        adapted by Jean-Paul ROUBELAT F6FBB 10/31/90
**************************************************************/

#include <serv.h>
#include <crc.h>

static FILE *infile, *outfile;
static char *in_f, *ou_f;
static unsigned long int textsize, codesize, printcount;
static char *head;
static char bin_header[257];
static short headlen;
static void write_huf_error (char *);
static short take (void);
static long numero;

static ushort crc;
static bullist *pbul;
static short basic;
static short init_huf = 0;
static int crlf = 0;

/********** LZSS compression **********/

#define N               2048  /* buffer size */
#define F               60          /* lookahead buffer size */
#define THRESHOLD       2
#define NIL             N           /* leaf of tree */

static unsigned char text_buf[N + F - 1];
static ushort chck;
static short match_position, match_length;
static short *lson, *rson, *dad;

/* Declaration de fonctions */

static short crc_fgetc (FILE *);
static short crc_fputc (short, FILE *);

static void ins_route (int, char *);

/**********************/


char *make_header (bullist * pbul, char *header)
{
      long temps;
      struct tm *sdate;
      char tempo[200];
      bullist *psauv;

      psauv = ptmes;
      ptmes = pbul;

      temps = ptmes->date;
      sdate = gmtime (&temps);

      if (std_header & 8)
            sprintf (tempo, "R:%02d%02d%02d/%02d%02dZ %%N@%%R%s",
                         sdate->tm_year % 100, sdate->tm_mon + 1, sdate->tm_mday,
                         sdate->tm_hour, sdate->tm_min, txtfwd);
      else
            sprintf (tempo, "R:%02d%02d%02d/%02d%02dZ @:%%R #:%%N%s",
                         sdate->tm_year % 100, sdate->tm_mon + 1, sdate->tm_mday,
                         sdate->tm_hour, sdate->tm_min, txtfwd);
      n_cpy (150, header, var_txt (tempo));

      if (((std_header & 4) == 0) && (strlen (header) > 79))
      {
            char *ptr;

            ptr = header + 79;
            while (*ptr != ' ')
            {
                  --ptr;
            }
            *ptr = '\0';
      }
      strcat (header, "\r");

      ptmes = psauv;

      return (header);
}


void dde_huf (int voie, bullist * pbul, int mode)
{
      desc_huf pthuf;
      long taille;
      FILE *fptr;
      char fic[128];
      char temp[128];

      make_header (pbul, pthuf.header);   /* <--------- A mettre ds ENCODE */
      pthuf.next = NULL;
      pthuf.voie = voie;
      pthuf.mode = mode;
      pthuf.bull = pbul;

      deb_io ();
      taille = 0L;
      if (pthuf.mode == ENCODE)
      {
            strcpy (fic, mess_name (MBINDIR, pthuf.bull->numero, temp));
            if ((fptr = fopen (fic, "r")) != NULL)
            {
                  if (fread (&taille, sizeof (long), 1, fptr) == 0)
                          taille = 0L;

                  fclose (fptr);
            }
      }
      fin_io ();
      if (taille == 0L)
      {
            taille = lzhuf (&pthuf);
      }

      svoie[voie]->ask = taille;
}

static short crc_fputc (short c, FILE * outfile)
{
      crc = updcrc (c, crc);
      chck += (c & 0xff);
      return (fputc (c, outfile));
}

static short crc_fgetc (FILE * infile)
{
      short retour = getc (infile);

      if (retour != -1)
      {
            crc = updcrc (retour, crc);
      }
      return (retour);
}

/*
 * Date en chaine de caracteres sous la forme 960225 (25fev 96)
 * Retour en secondes depuis le 1 Jan 1970
 */
long date_to_time (char *indd)
{
      static char Days[12] =
      {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

      long x;
      register short i;
      register short days;
      short jour, mois, annee;

      for (i = 0; i < 6; i++)
            if (!isdigit (indd[i]))
                  return (0L);

      if (indd[0] < '8')
            annee = ((indd[0] - '0') * 10) + 20 + (indd[1] - '0');
      else
            annee = ((indd[0] - '8') * 10) + (indd[1] - '0');
      mois = ((indd[2] - '0') * 10) + (indd[3] - '0');
      jour = ((indd[4] - '0') * 10) + (indd[5] - '0');

      if ((annee < 0) || (jour < 1) || (jour > 31) || (mois < 1) || (mois > 12))
      {
            /* La date est incoherente */
            x = 0L;
      }
      else
      {
            x = 315532800L + _timezone;         /* Convertit de 1980 a 1970 */
            x += (long) (annee >> 2) * 126230400L;    /* 4 annees */
            x += (long) (annee & 3) * 31536000L;      /* 1 annee */
            if (annee & 3)
                  x += 86400L;
            days = 0;
            i = mois - 1;
            while (i > 0)
            {
                  i--;
                  days += Days[i];
            }
            days += jour - 1;
            if ((mois > 2) && ((annee & 3) == 0))
                  days++;                       /* bissextile */
            x += ((long) days * 86400L);
      }
      return (x);
}

/*
 * Heure sous la forme 1031 (10h31mn)
 * Retour en secondes depuis 00h00
 */

long hour_to_time (char *indd)
{
      long x;
      register short i;
      short hour, minute;

      for (i = 0; i < 4; i++)
            if (!isdigit (indd[i]))
                  return (0L);

      hour = ((indd[0] - '0') * 10) + (indd[1] - '0');
      minute = ((indd[2] - '0') * 10) + (indd[3] - '0');

      x = (long) hour *3600L + (long) minute *60L;

      return (x);
}

char *bbs_via (char *s)
{
      short nb = 0;
      static char bbs[7];

      while (ISGRAPH (*s) && (*s != '.'))
      {
            if (nb == 6)
                  break;
            bbs[nb++] = toupper (*s);
            ++s;
      }
      bbs[nb] = '\0';
      return (bbs);
}



static void ins_route (int voie, char *route)
{
      int i, alloue = 0;
      Hroute *pcurr, *pprec;

      if (svoie[voie]->r_tete == NULL)
      {
            svoie[voie]->r_tete = svoie[voie]->r_curr = (Route *) m_alloue (sizeof (Route));
            alloue = 1;
      }
      if (svoie[voie]->r_pos == NBROUTE)
      {
            svoie[voie]->r_curr->suite = (Route *) m_alloue (sizeof (Route));
            svoie[voie]->r_curr = svoie[voie]->r_curr->suite;
            alloue = 1;
      }
      if (alloue)
      {
            svoie[voie]->r_pos = 0;
            svoie[voie]->r_curr->suite = NULL;
            for (i = 0; i < NBROUTE; i++)
                  *(svoie[voie]->r_curr->call[i]) = '\0';
      }
      strn_cpy (6, svoie[voie]->r_curr->call[svoie[voie]->r_pos++], bbs_via (route));


      if (h_ok)
      {
            pcurr = throute;
            pprec = NULL;

            if (pcurr)
            {
                  while (pcurr)
                  {
                        pprec = pcurr;
                        pcurr = pcurr->suiv;
                  }
                  pcurr = pprec->suiv = (Hroute *) m_alloue (sizeof (Hroute));
            }
            else
            {
                  pcurr = throute = (Hroute *) m_alloue (sizeof (Hroute));
            }
            strn_cpy (40, pcurr->route, route);
            pcurr->suiv = NULL;
      }
}

void analyse_header (int voie, char *ptr)
{
      int c;
      int champ;
      int nb;
      int bbs;
      long date;
      char rbbs[80];
      char home[41];
      char qth[31];
      char zip[13];

      ptr += 2;
      champ = 2;
      nb = 0;
      bbs = 0;

      *home = *zip = *qth = '\0';
      date = 0L;

      svoie[voie]->mess_num = -1L;

      do
      {

            c = *ptr;

            switch (champ)
            {

            case 0:
                  switch (c)
                  {
                  case '@':
                        bbs = 1;
                        champ = 3;
                        nb = 0;
                        break;
                  case '#':
                        champ = 6;
                        nb = 0;
                        break;
                  case '$':
                        champ = 7;
                        nb = 0;
                        break;
                  case '[':
                        champ = 4;
                        nb = 0;
                        break;
                  case 'Z':
                        if (*(ptr + 1) == ':')
                        {
                              ++ptr;
                              champ = 5;
                              nb = 0;
                        }
                        break;
                  default:
                        if ((bbs == 0) && (isdigit (c)))
                        {
                              nb = 0;
                              rbbs[nb++] = c;
                              champ = 6;
                        }
                  }

            case 1:
                  if (isspace (c))
                        champ = 0;
                  break;

            case 2:                       /* Lecture de la date - Mettre la date la plus ancienne */
                  if (nb <= 10)
                        rbbs[nb] = c;
                  if (nb == 10)
                  {
                        rbbs[11] = '\0';
                        rbbs[6] = '\0';
                        if ((date = date_to_time (rbbs)) != 0L)
                        {
                              date += hour_to_time (rbbs + 7);
                              svoie[voie]->messdate = date;
                        }
                        champ = 1;
                  }
                  ++nb;
                  break;

            case 3:                       /* Lecture du home BBS */
                  if ((nb == 0) && (c == ':'))
                        break;
                  if ((ISGRAPH (c)) && (nb < 40))
                  {
                        rbbs[nb++] = c;
                  }
                  else
                  {
                        rbbs[nb] = '\0';
                        ins_route (voie, rbbs);
                        strn_cpy (40, home, rbbs);
                        strn_cpy (40, svoie[voie]->mess_home, rbbs);
                        svoie[voie]->header = 1;
                        champ = 0;
                  }
                  break;

            case 4:                       /* Lecture du Qth */
                  if ((c != ']') && (nb < 30))
                  {
                        rbbs[nb++] = c;
                  }
                  else
                  {
                        rbbs[nb] = '\0';
                        n_cpy (30, qth, rbbs);
                        champ = 0;
                  }
                  break;

            case 5:                       /* Lecture du Zip Code */
                  if ((ISGRAPH (c)) && (nb < 8))
                  {
                        rbbs[nb++] = c;
                  }
                  else
                  {
                        rbbs[nb] = '\0';
                        strn_cpy (8, zip, rbbs);
                        champ = 0;
                  }
                  break;
            case 6:                       /* Lecture du home premier numero */
                  if ((nb == 0) && (c == ':'))
                        break;
                  if ((isdigit (c)) && (nb < 10))
                  {
                        rbbs[nb++] = c;
                  }
                  else
                  {
                        rbbs[nb] = '\0';
                        if (nb)
                              svoie[voie]->mess_num = atol (rbbs);
                        if ((bbs == 0) && (c == '@'))
                        {
                              bbs = 1;
                              champ = 3;
                              nb = 0;
                        }
                        else
                              champ = 0;
                  }
                  break;
            case 7:                       /* Lecture du BID/MID */
                  if ((nb == 0) && (c == ':'))
                        break;
                  if ((ISGRAPH (c)) && (nb < 12))
                  {
                        rbbs[nb++] = c;
                  }
                  else
                  {
                        rbbs[nb] = '\0';
                        if (nb)
                              strn_cpy (12, svoie[voie]->mess_bid, rbbs);
                        champ = 0;
                  }
                  break;

            }

            ++ptr;
      }
      while (ISPRINT (c));

      header_wp (date, home, qth, zip);
}

void entete_mess_fwd (bullist * pbul, char *header)
{
      char s[128];
      bullist *sav_bul;

      deb_io ();
      sav_bul = ptmes;
      ptmes = pbul;
      *msg_header = '\0';

      if ((ptmes->type == 'A') || (strcmp (ptmes->desti, "WP") == 0))
      {
            if (*(ptmes->bbsf) == '\0')
            {
                  strcpy (msg_header, header);
                  strcat (msg_header, "\r");
            }
      }
      else if (*(ptmes->bbsf))
      {
            strcpy (msg_header, header);
      }
      else
      {
            strcpy (msg_header, header);
            sprintf (s, "\rFrom: %s@%s\rTo  : %s@%s\r\r",
                         ptmes->exped, mypath, ptmes->desti, ptmes->bbsv);
            strcat (msg_header, s);
      }

      ptmes = sav_bul;
      fin_io ();
}


static void write_huf_error (char *filename)
{
      deb_io ();
      fclose (infile);
      fclose (outfile);
      unlink (ou_f);
      write_error (filename);
      fin_io ();
}


static void InitTree (void)         /* initialize trees */
{
      int i;

      for (i = N + 1; i <= N + 256; i++)
            rson[i] = NIL;                /* root */
      for (i = 0; i < N; i++)
            dad[i] = NIL;                 /* node */
}


static void InsertNode (short r)    /* insert to tree */
{
      short i, p, cmp;
      unsigned char *key;
      ushort c;

      cmp = 1;
      key = &text_buf[r];
      p = N + 1 + key[0];
      rson[r] = lson[r] = NIL;
      match_length = 0;
      for (;;)
      {
            if (cmp >= 0)
            {
                  if (rson[p] != NIL)
                        p = rson[p];
                  else
                  {
                        rson[p] = r;
                        dad[r] = p;
                        return;
                  }
            }
            else
            {
                  if (lson[p] != NIL)
                        p = lson[p];
                  else
                  {
                        lson[p] = r;
                        dad[r] = p;
                        return;
                  }
            }
            for (i = 1; i < F; i++)
                  if ((cmp = key[i] - text_buf[p + i]) != 0)
                        break;
            if (i > THRESHOLD)
            {
                  if (i > match_length)
                  {
                        match_position = ((r - p) & (N - 1)) - 1;
                        if ((match_length = i) >= F)
                              break;
                  }
                  else if (i == match_length)
                  {
                        if ((c = ((r - p) & (N - 1)) - 1) < match_position)
                        {
                              match_position = c;
                        }
                  }
            }
      }
      dad[r] = dad[p];
      lson[r] = lson[p];
      rson[r] = rson[p];
      dad[lson[p]] = r;
      dad[rson[p]] = r;
      if (rson[dad[p]] == p)
            rson[dad[p]] = r;
      else
            lson[dad[p]] = r;
      dad[p] = NIL;                       /* remove p */
}


static void DeleteNode (short p)    /* remove from tree */
{
      short q;

      if (dad[p] == NIL)
            return;                             /* not registered */
      if (rson[p] == NIL)
            q = lson[p];
      else if (lson[p] == NIL)
            q = rson[p];
      else
      {
            q = lson[p];
            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[p];
                  dad[lson[p]] = q;
            }
            rson[q] = rson[p];
            dad[rson[p]] = q;
      }
      dad[q] = dad[p];
      if (rson[dad[p]] == p)
            rson[dad[p]] = q;
      else
            lson[dad[p]] = q;
      dad[p] = NIL;
}


/* Huffman coding */

#define N_CHAR   (256 - THRESHOLD + F)
/* kinds of characters (character code = 0..N_CHAR-1) */
#define T        (N_CHAR * 2 - 1)   /* size of table */
#define R        (T - 1)            /* position of root */
#define MAX_FREQ 0x8000             /* updates tree when the */
/* root frequency comes to this value. */

/* table for encoding and decoding the upper 6 bits of position */

/* for encoding */
static 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
};


static 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
};


/* for decoding */
static uchar d_code[256] =
{
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
      0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
      0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
      0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
      0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
      0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
      0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
      0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
      0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
      0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
      0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
      0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
      0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
      0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
      0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
      0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
      0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
      0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
      0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
      0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
      0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
      0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};


static uchar d_len[256] =
{
      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
      0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
      0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
      0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
      0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
      0x06, 0x06, 0x06, 0x06, 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,
      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,
};


static ushort *freq;                /* frequency table */

/*
   pointers to parent nodes, except for the
   elements [T..T + N_CHAR - 1] which are used to get
   the positions of leaves corresponding to the codes.
 */

static short *prnt;

static short *fils;                       /* pointers to child nodes (fils[], fils[] + 1) */

static ushort getbuf;
static uchar getlen;

static short scan_header (char *chaine)
{
      char *ptr = bin_header;

      while ((*ptr++ = *chaine) != '\0')
      {
            if (*chaine == '\r')
                  *ptr++ = '\n';
            ++chaine;
      }
      return (strlen (bin_header));
}


static short take (void)
{
      short c;

      if (headlen)
      {
            --headlen;
            c = ((short) *head++ & 0xff);
      }
      else
      {
            /* Gestion du LF -> CRLF */

            if (crlf)
            {
                  c = '\n';
                  crlf = 0;
            }
            else
            {
                  do
                  {
                        /* Ignore les CR */
                        c = getc (infile);
                  }
                  while (c == '\r');

                  if (c == '\n')
                  {
                        crlf = c;
                        c = '\r';
                  }
            }

      }
      return (c);
}


static short GetBit (void)          /* get one bit */
{
      short i;

      while (getlen <= 8)
      {
            if ((i = crc_fgetc (infile)) < 0)
                  i = 0;
            getbuf |= i << (8 - getlen);
            getlen += 8;
      }
      i = getbuf;
      getbuf <<= 1;
      getlen--;
      return (i < 0);
}


static short GetByte (void)         /* get one byte */
{
      ushort i;

      while (getlen <= 8)
      {
            if ((i = crc_fgetc (infile)) == 0xffff)
                  i = 0;
            getbuf |= i << (8 - getlen);
            getlen += 8;
      }
      i = getbuf;
      getbuf <<= 8;
      getlen -= 8;
      return i >> 8;
}


static ushort putbuf;
static uchar putlen;

static void Putcode (short l, ushort c)         /* output c bits of code */
{
      putbuf |= c >> putlen;
      if ((putlen += l) >= 8)
      {
            if (crc_fputc (putbuf >> 8, outfile) == EOF)
            {
                  write_huf_error (ou_f);
            }
            if ((putlen -= 8) >= 8)
            {
                  if (crc_fputc (putbuf, outfile) == EOF)
                  {
                        write_huf_error (ou_f);
                  }
                  codesize += 2;
                  putlen -= 8;
                  putbuf = c << (l - putlen);
            }
            else
            {
                  putbuf <<= 8;
                  codesize++;
            }
      }
}


/* initialization of tree */

static void StartHuff (void)
{
      short i, j;

      for (i = 0; i < N_CHAR; i++)
      {
            freq[i] = 1;
            fils[i] = i + T;
            prnt[i + T] = i;
      }
      i = 0;
      j = N_CHAR;
      while (j <= R)
      {
            freq[j] = freq[i] + freq[i + 1];
            fils[j] = i;
            prnt[i] = prnt[i + 1] = j;
            i += 2;
            j++;
      }
      freq[T] = 0xffff;
      prnt[R] = 0;
}


/* reconstruction of tree */

static void reconst (void)
{
      short i, j, k;
      ushort f, l;

      /* collect leaf nodes in the first half of the table */
      /* and replace the freq by (freq + 1) / 2. */
      j = 0;
      for (i = 0; i < T; i++)
      {
            if (fils[i] >= T)
            {
                  freq[j] = (freq[i] + 1) / 2;
                  fils[j] = fils[i];
                  j++;
            }
      }
      /* begin constructing tree by connecting sons */
      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;
            memmove (&freq[k + 1], &freq[k], l);
            freq[k] = f;
            memmove (&fils[k + 1], &fils[k], l);
            fils[k] = i;
      }
      /* connect prnt */
      for (i = 0; i < T; i++)
      {
            if ((k = fils[i]) >= T)
            {
                  prnt[k] = i;
            }
            else
            {
                  prnt[k] = prnt[k + 1] = i;
            }
      }
}


/* increment frequency of given code by one, and update tree */

static void update (short c)
{
      short i, j, k, l;

      if (freq[R] == MAX_FREQ)
      {
            reconst ();
      }
      c = prnt[c + T];
      do
      {
            k = ++freq[c];

            /* if the order is disturbed, exchange nodes */
            if (k > freq[l = c + 1])
            {
                  while (k > freq[++l])
                        ;
                  l--;
                  freq[c] = freq[l];
                  freq[l] = k;

                  i = fils[c];
                  prnt[i] = l;
                  if (i < T)
                        prnt[i + 1] = l;

                  j = fils[l];
                  fils[l] = i;

                  prnt[j] = c;
                  if (j < T)
                        prnt[j + 1] = c;
                  fils[c] = j;

                  c = l;
            }
      }
      while ((c = prnt[c]) != 0);   /* repeat up to root */
}


static ushort code, len;

static void EncodeChar (ushort c)
{
      ushort i;
      short j, k;

      i = 0;
      j = 0;
      k = prnt[c + T];

      /* travel from leaf to root */
      do
      {
            i >>= 1;

            /* if node's address is odd-numbered, choose bigger brother node */
            if (k & 1)
                  i += 0x8000;

            j++;
      }
      while ((k = prnt[k]) != R);
      Putcode (j, i);
      code = i;
      len = j;
      update (c);
}


static void EncodePosition (ushort c)
{
      ushort i;

      /* output upper 6 bits by table lookup */
      i = c >> 6;
      Putcode (p_len[i], (ushort) p_code[i] << 8);

      /* output lower 6 bits verbatim */
      Putcode (6, (c & 0x3f) << 10);
}


static void EncodeEnd (void)
{
      if (putlen)
      {
            if (crc_fputc (putbuf >> 8, outfile) == EOF)
            {
                  write_huf_error (ou_f);
            }
            codesize++;
      }
}


static short DecodeChar (void)
{
      ushort c;

      c = fils[R];

      /* travel from root to leaf, */
      /* choosing the smaller child node (fils[]) if the read bit is 0, */
      /* the bigger (fils[]+1} if 1 */
      while (c < T)
      {
            c += GetBit ();
            c = fils[c];
      }
      c -= T;
      update (c);
      return c;
}


static short DecodePosition (void)
{
      ushort i, j, c;

      /* recover upper 6 bits from table */
      i = GetByte ();
      c = (ushort) d_code[i] << 6;
      j = d_len[i];

      /* read lower 6 bits verbatim */
      j -= 2;
      while (j--)
      {
            i = (i << 1) + GetBit ();
      }
      return c | (i & 0x3f);
}


/* compression */

static void Encode (short voie)     /* compression */
{
      char temp[128];
      long filesize;
      short i, c, len, r, s, last_match_length;

      head = bin_header;
      fflush (infile);
#if defined(__MSDOS__) || defined(__WINDOWS__)
      filesize = filelength (fileno (infile)) + (long) headlen;
#else
      filesize = headlen;
      /* Read the file to compute the filesize under unix. Terminations = CRLF */
      while ((c = getc (infile)) != EOF)
      {
            /* Ignore '\r' */
            if (c == '\r')
                  continue;

            /* LF -> CRLF */
            if (c == '\n')
                  ++filesize;

            ++filesize;
      }
      rewind (infile);
#endif

      textsize = 0L;                      /* rewind and re-read */
      crc = 0;

      /* CRC and textsize are 0 : no need to swap them for motorola */
      
      if (basic)
      {
            if (fwrite (&textsize, sizeof textsize, 1, outfile) < 1)
                  write_huf_error (ou_f);       /* output size of text */
      }
      else
      {
            if (fwrite (&crc, sizeof (crc), 1, outfile) < 1)
                  write_huf_error (ou_f);       /* output size of text */

            memcpy (temp, &filesize, sizeof (filesize));
            if (moto)
            {
                  for (i = sizeof (filesize) -1 ; i >= 0 ; i-- )
                        crc_fputc (temp[i], outfile);
            }
            else
            {
                  for (i = 0; i < sizeof (filesize); i++)
                        crc_fputc (temp[i], outfile);
            }
      }

      StartHuff ();
      InitTree ();
      s = 0;
      r = N - F;
      for (i = s; i < r; i++)
            text_buf[i] = ' ';
      for (len = 0; len < F && (c = take ()) != EOF; len++)
            text_buf[r + len] = c;
      textsize = len;
      for (i = 1; i <= F; i++)
            InsertNode (r - i);
      InsertNode (r);
      do
      {
            if (match_length > len)
                  match_length = len;
            if (match_length <= THRESHOLD)
            {
                  match_length = 1;
                  EncodeChar (text_buf[r]);
            }
            else
            {
                  EncodeChar (255 - THRESHOLD + match_length);
                  EncodePosition (match_position);
            }
            last_match_length = match_length;
            for (i = 0; i < last_match_length && (c = take ()) != EOF; i++)
            {
                  DeleteNode (s);
                  text_buf[s] = c;
                  if (s < F - 1)
                        text_buf[s + N] = c;
                  s = (s + 1) & (N - 1);
                  r = (r + 1) & (N - 1);
                  InsertNode (r);
            }
            if ((textsize += i) > printcount)
            {
                  compress_display (1, (textsize * 100) / filesize, numero);
                  printcount += 500;
            }
            while (i++ < last_match_length)
            {
                  DeleteNode (s);
                  s = (s + 1) & (N - 1);
                  r = (r + 1) & (N - 1);
                  if (--len)
                        InsertNode (r);
            }
      }
      while (len > 0);
      EncodeEnd ();


      compress_display (1, 100, numero);

      /* Ecrit le crc du fichier original */
      deb_io ();

      rewind (outfile);
      if (basic)
      {
            memcpy (temp, &textsize, sizeof (textsize));
            if (moto)
            {
                  for (i = sizeof (textsize) -1 ; i >= 0 ; i-- )
                        crc_fputc (temp[i], outfile);
            }
            else
            {
                  for (i = 0; i < sizeof (textsize); i++)
                        crc_fputc (temp[i], outfile);
            }
      }
      else
      {
            if (moto)
                  crc = xendien (crc);
            if (fwrite (&crc, sizeof (crc), 1, outfile) < 1)
                  write_huf_error (ou_f);       /* output crc */
      }

      if (filesize != textsize)
      {
            cprintf ("Phase error !\r\n");
      }

      aff_header (voie);
      if (numero)
            sprintf (temp, "Compress #%ld In: %-6ld- Out: %-6ld- Compress: %ld %%\r\n",
               numero, textsize, codesize, 100L - ((codesize * 100L) / textsize));
      else
            sprintf (temp, "Compress XFwd In: %-6ld- Out: %-6ld- Compress: %ld %%\r\n",
                         textsize, codesize, 100L - ((codesize * 100L) / textsize));
      winputs (voie, W_SNDT, temp);
      textsize = codesize + 4;
      fin_io ();
}


void check_bin (bullist * pbul, char *ptr)
{
#define NB_PATTERN 8
#define LG_PATTERN 6

      static char pattern[NB_PATTERN][LG_PATTERN + 1] =
      {
            " go_7+",
            " go_te",
            "\000\000\000\000\000\000",
            "\000\000\000\000\000\000",
            "\000\000\000\000\000\000",
            "\000\000\000\000\000\000",
            "\000\000\000\000\000\000",
            "\000\000\000\000\000\000"
      };

      short i;

      /* Checks for data message and validates bin flag */

      for (i = 0; i < NB_PATTERN; i++)
      {
            if (!(*pattern[i]))
                  break;
            if (strncmp (pattern[i], ptr, LG_PATTERN) == 0)
            {
                  pbul->bin = 1;
            }
      }
}

static void test_ligne (int voie, char *ligne)
{
      char deb[5];

      strn_cpy (4, deb, ligne);

      if ((svoie[voie]->m_ack) && (strncmp (deb, "/ACK", 4) == 0))
      {
            svoie[voie]->m_ack = 2;
      }
      else if ((svoie[voie]->entete) && (strncmp (deb, "R:", 2) == 0))
      {
            analyse_header (voie, ligne);
      }
      else if (*ligne)
      {
            check_bin (pbul, ligne);
            svoie[voie]->entete = 0;
      }
}


static int Decode (int voie)  /* recover */
{
      char temp[128];
      char ligne[82];
      short i, j, k, r, c;
      short pos = 0;
      ushort fcrc;
      unsigned long int count;

      deb_io ();

      fseek (infile, 0L, 2);
      codesize = ftell (infile) - sizeof (textsize);

      if (!basic)
      {
            fseek (infile, 20L, 0);

            textsize = -1;
            crc = 0;
            if ((svoie[voie]->fbb >= 2) && (fread (&fcrc, sizeof fcrc, 1, infile) < 1))
            {
                  if (!svoie[CONSOLE]->sta.connect)
                        cprintf ("File empty (%ld)!!\r\n", textsize);
                  fin_io ();
                  return (0);
            }

            if (moto)
                  fcrc = xendien (fcrc);
                  
            memset (temp, 0, sizeof (textsize));
            if (moto)
            {
                  for (i = sizeof (textsize) -1 ; i >= 0 ; i-- )
                        temp[i] = crc_fgetc (infile);
            }
            else
            {
                  for (i = 0; i < sizeof (textsize); i++)
                        temp[i] = crc_fgetc (infile);
            }
            
            memcpy (&textsize, temp, sizeof (textsize));

            if ((textsize == 0L) || (textsize == 0xffffffffL))
            {
                  if (!svoie[CONSOLE]->sta.connect)
                        cprintf ("File empty (%ld)!!\r\n", textsize);
                  fin_io ();
                  return (0);
            }

            if (textsize > (100L * codesize))
            {
                  if (!svoie[CONSOLE]->sta.connect)
                        cprintf ("Cannot decompress to %ld bytes!!\r\n", textsize);
                  fin_io ();
                  return (0);
            }

      }
      else
      {
            rewind (infile);
            if ((fread (&textsize, sizeof textsize, 1, infile) < 1) || (textsize == 0))
            {
                  if (!svoie[CONSOLE]->sta.connect)
                        cprintf ("File empty (%ld)!!\r\n", textsize);
                  fin_io ();
                  return (0);
            }

            if (moto)
                  textsize = xendienl (textsize);
                  
            if (textsize > (100L * codesize))
            {
                  if (!svoie[CONSOLE]->sta.connect)
                        cprintf ("Cannot decompress to %ld bytes!!\r\n", textsize);
                  fin_io ();
                  return (0);
            }
      }

      fin_io ();

      StartHuff ();
      for (i = 0; i < N - F; i++)
            text_buf[i] = ' ';
      r = N - F;
      for (count = 0; count < textsize;)
      {
            c = DecodeChar ();
            if (c < 256)
            {
                  if (!basic)
                  {
                        if ((c == '\r') || (c == '\n'))
                        {
                              ligne[pos] = '\0';
                              test_ligne (voie, ligne);
                              pos = 0;
                        }
                        else if (pos < 80)
                        {
                              ligne[pos++] = c;
                        }
                  }
                  if ((c == '\n') || (c == '\r'))
                  {
                        if ((crlf == 0) || (crlf == c))
                        {
                              crlf = c;
                              if (fputc ('\r', outfile) == EOF)
                              {
                                    write_huf_error (ou_f);
                              }
                              if (fputc ('\n', outfile) == EOF)
                              {
                                    write_huf_error (ou_f);
                              }
                        }
                  }
                  else
                  {
                        crlf = 0;
                        if (fputc (c, outfile) == EOF)
                        {
                              write_huf_error (ou_f);
                        }
                  }
                  text_buf[r++] = c;
                  r &= (N - 1);
                  count++;
            }
            else
            {
                  i = (r - DecodePosition () - 1) & (N - 1);
                  j = c - 255 + THRESHOLD;
                  for (k = 0; k < j; k++)
                  {
                        c = text_buf[(i + k) & (N - 1)];
                        if (!basic)
                        {
                              if ((c == '\r') || (c == '\n'))
                              {
                                    ligne[pos] = '\0';
                                    test_ligne (voie, ligne);
                                    pos = 0;
                              }
                              else if (pos < 80)
                              {
                                    ligne[pos++] = c;
                              }
                        }
                        /*
                           if (fputc (c, outfile) == EOF)
                           {
                           write_huf_error (ou_f);
                           }
                         */
                        if ((c == '\n') || (c == '\r'))
                        {
                              if ((crlf == 0) || (crlf == c))
                              {
                                    crlf = c;
                                    if (fputc ('\r', outfile) == EOF)
                                    {
                                          write_huf_error (ou_f);
                                    }
                                    if (fputc ('\n', outfile) == EOF)
                                    {
                                          write_huf_error (ou_f);
                                    }
                              }
                        }
                        else
                        {
                              crlf = 0;
                              if (fputc (c, outfile) == EOF)
                              {
                                    write_huf_error (ou_f);
                              }
                        }
                        text_buf[r++] = c;
                        r &= (N - 1);
                        count++;
                  }
            }
            if (count > printcount)
            {
                  compress_display (2, (count * 100) / textsize, numero);
                  printcount += 500;
            }
      }
      compress_display (2, 100, numero);
      deb_io ();
      aff_header (voie);
      if (numero)
            sprintf (temp, "Decompress #%ld In: %-6ld- Out: %-6ld- Compress: %ld %%\r\n",
               numero, codesize, textsize, 100L - ((codesize * 100L) / textsize));
      else
            sprintf (temp, "Decompress XFwd In: %-6ld- Out: %-6ld- Compress: %ld %%\r\n",
                         codesize, textsize, 100L - ((codesize * 100L) / textsize));
      winputs (voie, W_RCVT, temp);
      if ((!basic) && (svoie[voie]->fbb >= 2) && (crc != fcrc))
      {
            if (!svoie[CONSOLE]->sta.connect)
                  cprintf ("CRC Error : file %04x, computed %04x\r\n", fcrc, crc);
            fin_io ();
            return (0);
      }
      fin_io ();
      return (1);
}


void end_lzhuf (void)
{
      if (init_huf)
      {
            m_libere (lson, sizeof (short) * (N + 1));
            m_libere (rson, sizeof (short) * (N + 257));
            m_libere (dad, sizeof (short) * (N + 1));
            m_libere (prnt, sizeof (short) * (T + N_CHAR));
            m_libere (fils, sizeof (short) * T);

            m_libere (freq, sizeof (ushort) * (T + 1));
            init_huf = 0;
      }
}


static void alloue_lzhuf_buffers (void)
{
      lson = (short *) m_alloue (sizeof (short) * (N + 1));
      rson = (short *) m_alloue (sizeof (short) * (N + 257));
      dad = (short *) m_alloue (sizeof (short) * (N + 1));
      prnt = (short *) m_alloue (sizeof (short) * (T + N_CHAR));
      fils = (short *) m_alloue (sizeof (short) * T);

      freq = (ushort *) m_alloue (sizeof (ushort) * (T + 1));

      init_huf = 1;
}


static void init_huffman (void)
{
      static int init = 0;

      if (!init)
      {
            alloue_lzhuf_buffers ();
            init = 1;
      }
}

long lzhuf (desc_huf * huf)
{
      char bin_file[128];
      char tmp_file[128];
      char asc_file[128];

      init_huffman ();

      basic = 0;
      crlf = 0;

      numero = huf->bull->numero;

      pbul = huf->bull;

      mess_name (MBINDIR, numero, bin_file);
      mess_name (MESSDIR, numero, asc_file);

      if (huf->mode == ENCODE)
      {
            temp_name (huf->voie, tmp_file);
            in_f = asc_file;
            ou_f = tmp_file;
            deb_io ();
            entete_mess_fwd (pbul, huf->header);
            headlen = scan_header (msg_header);
            fin_io ();
      }
      else if (huf->mode == DECODE)
      {
            strcpy (tmp_file, svoie[huf->voie]->sr_fic);
            in_f = tmp_file;
            ou_f = asc_file;
      }

      if ((outfile = fopen (ou_f, "wb")) == NULL)
            write_error (ou_f);

      if ((infile = fopen (in_f, "rb")) == NULL)
      {
            fprintf (outfile, "\r\nMessage file %s missing in %s\r\n", in_f, mycall);
            fclose (outfile);
            return (40L);
      }

      textsize = 0;                       /* text size counter */
      codesize = 0;                       /* code size counter */
      printcount = 0;                     /* counter for reporting progress every 1K bytes */
      getbuf = getlen = putbuf = putlen = 0;

      if (huf->mode == ENCODE)
      {
            Encode (huf->voie);
      }
      else if (huf->mode == DECODE)
      {
            if (!Decode (huf->voie))
                  textsize = -1L;
      }

      fclose (infile);
      fclose (outfile);

      deb_io ();
      if (huf->mode == ENCODE)
      {
            rename_temp (huf->voie, bin_file);
      }

      tot_mem = 0;
      free_mem ();
      compress_display (0, 0, numero);

      fin_io ();

      return (textsize);
}

long basic_lzhuf (int mode, char *in_file, char *out_file)
{
      chck = 0;
      basic = 1;
      crlf = 0;

      init_huffman ();

      in_f = in_file;
      ou_f = out_file;

      if ((infile = fopen (in_f, "rb")) == NULL)
            return 0L;

      if ((outfile = fopen (ou_f, "wb")) == NULL)
            write_error (ou_f);

      numero = 0;
      textsize = 0;                       /* text size counter */
      codesize = 0;                       /* code size counter */
      printcount = 0;                     /* counter for reporting progress every 1K bytes */
      getbuf = getlen = putbuf = putlen = 0;

      if (mode == ENCODE)
      {
            Encode (voiecur);
      }
      else if (mode == DECODE)
      {
            if (!Decode (voiecur))
                  textsize = -1L;
      }

      fclose (infile);
      fclose (outfile);

      tot_mem = 0;
      free_mem ();
      compress_display (0, 0, 0);

      svoie[voiecur]->checksum = chck;
      return (textsize);
}

Generated by  Doxygen 1.6.0   Back to index