home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / yacoder.lha / yacoder / codes.c next >
C/C++ Source or Header  |  1998-05-07  |  5KB  |  242 lines

  1. /*
  2.  * $Header: /usr/people/tcl/src/uutar/RCS/codes.c,v 1.1.1.4 1993/09/11 22:42:44 tcl Exp $
  3.  * Tom Lawrence
  4.  * tcl@sgi.com
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include "codes.h"
  10.  
  11. /* see codes.h */
  12. int numchars;
  13. struct code codes[256];
  14.  
  15. /* initialize a subset of the codes array. val and len define a variable
  16.  * length bitfield. The array elements will be set up so that any element
  17.  * of the array whose index is a left-aligned superset of this bitfield
  18.  * will contain the given output ascii character. E.g. if the bitfield is
  19.  * 10010, then all elements in the array with subscript 10010xxx for all
  20.  * xxx, will store the given ascii code, and the length of the bitfield,
  21.  * in this case 5.
  22.  */
  23. static void
  24. init_encodeval(codes, val, len, ascii)
  25.     struct code *codes;
  26.     int val;
  27.     int len;
  28.     int ascii;
  29. {
  30.     int shift, stop;
  31.  
  32.     /* determine how far the code must be shifted to be 
  33.      * MSB justified in the byte
  34.      */
  35.     shift = 8 - len;
  36.  
  37.     /* calculate the upper bound of indices which this bitfield
  38.      * will match
  39.      */
  40.     stop = (val + 1) << shift;
  41.  
  42.     /* shift the code over to the left edge of the byte */
  43.     val <<= shift;
  44.  
  45.     /* thus, for every index in the 256 element array which has
  46.      * this code as a prefix
  47.      */
  48.     for(; val < stop; val++) {
  49.     /* store the code length and the printable character 
  50.      * it represents
  51.      */
  52.     codes[val].len = (char)len;
  53.     codes[val].code = (char)ascii;
  54.     }
  55. }
  56.  
  57. /* convert an ascii character code to an integer. The character code may
  58.  * be in decimal, hex or octal, or it may be an actual character escaped
  59.  * with a back-slash
  60.  */
  61. static int
  62. str2val(str)
  63.     char *str;
  64. {
  65.     int val;
  66.     char *end;
  67.  
  68.     while(*str == ' ' || *str == '\t')
  69.     str++;
  70.  
  71.     /* check if this is an escaped character */
  72.     if (*str == '\\') {
  73.     str++;
  74.     if (*str == 0) {
  75.         fprintf(stderr, "missing character in alphabet\n");
  76.         exit(1);
  77.     }
  78.     return((int)*str);
  79.     }
  80.  
  81.     val = (int)strtol(str, &end, 0);
  82.     if (end == str) {
  83.     if (*str)
  84.         fprintf(stderr, "invalid char \'%c\' in alphabet\n", *str);
  85.     else
  86.         fprintf(stderr, "empty numerical field in alphabet\n");
  87.     exit(1);
  88.     }
  89.     return(val);
  90. }
  91.  
  92. /* parse a range of characters for the output character set and mark each
  93.  * character as in use in the codes array. A range is either in the form
  94.  * num-num or just num
  95.  */
  96. static void
  97. parse_charval_range(range)
  98.     char *range;
  99. {
  100.     char *c, savec = 0;
  101.     int start, end, x;
  102.  
  103.     for(c = range; *c && *c != '-'; c++);
  104.     savec = *c;
  105.     *c = 0;
  106.  
  107.     start = str2val(range);
  108.     if (savec == '-') {
  109.     end = str2val(c + 1);
  110.     *c = savec;
  111.     for(x = start; x <= end; x++)
  112.         codes[x].inuse = 1;
  113.     }
  114.     else
  115.     codes[start].inuse = 1;
  116. }
  117.  
  118. /* parse a list of character ranges for the output character set and then
  119.  * parse each range found. A list is of the form range,range,...
  120.  */
  121. void
  122. parse_charval_list(list)
  123.     char *list;
  124. {
  125.     char *c1, *c2, savec2;
  126.     int x;
  127.  
  128.     for(x = 0; x < 256; x++)
  129.     codes[x].inuse = 0;
  130.  
  131.     c1 = list;
  132.     while(*c1) {
  133.     while(*c1 == ',')
  134.         c1++;
  135.     if (*c1 == 0)
  136.         return;
  137.     for(c2 = c1; *c2 && *c2 != ','; c2++);
  138.     savec2 = *c2;
  139.     *c2 = 0;
  140.     parse_charval_range(c1);
  141.     *c2 = savec2;
  142.     c1 = c2;
  143.     }
  144.     return;
  145. }
  146.  
  147. /* print out the character set in the form of a list of ranges, encoded
  148.  * in decimal
  149.  */
  150. void
  151. print_charval_list(fp)
  152.     FILE *fp;
  153. {
  154.     int x, usecomma;
  155.  
  156.     usecomma = 0;
  157.     for(x = 0; x < 256; x++) {
  158.     if (codes[x].inuse) {
  159.         if (usecomma)
  160.         putc(',', fp);
  161.         fprintf(fp, "%d", x);
  162.         usecomma = 1;
  163.         if (x < 255 && codes[x+1].inuse) {
  164.         putc('-', fp);
  165.         while(++x < 256 && codes[x].inuse);
  166.         fprintf(fp, "%d", x-1);
  167.         }
  168.     }
  169.     }
  170. }
  171.  
  172. /*
  173.  * Initialize the tables for encoding or decoding depending on the given
  174.  * direction. 
  175.  */
  176. void
  177. init_codes(direction)
  178.     int direction;
  179. {
  180.     int x, code, numchars;
  181.     int pof2, pof2len, half, whole;
  182.  
  183.     /* count how big our character set is */
  184.     numchars = 0;
  185.     for(x = 0; x < 256; x++)
  186.     if (codes[x].inuse)
  187.         numchars++;
  188.  
  189.     if (numchars < 2) {
  190.     fprintf(stderr,
  191.         "uutar: alphabet doesn't contain enough characters.\n");
  192.     exit(1);
  193.     }
  194.  
  195.     /* determine the lowest power of 2 that is >= numchars, and the number
  196.      * of bits needed to store that many values.
  197.      */
  198.     for(pof2 = 2, pof2len = 1; pof2 < numchars;
  199.     pof2 <<= 1, pof2len++);
  200.  
  201.     /* compute how many half codes we need */
  202.     half = pof2 - numchars;
  203.  
  204.     /* compute how many whole codes we need */
  205.     whole = numchars - half;
  206.  
  207.     /* create a variable length code for each valid entry */
  208.     code = 0;
  209.     x = -1;
  210.  
  211.     /* create the whole codes */
  212.     while(whole--) {
  213.     /* get next slot */
  214.     do x++; while(codes[x].inuse == 0);
  215.  
  216.     if (direction == DECODE) {
  217.         codes[x].code = (char)code;
  218.         codes[x].len = (char)pof2len;
  219.     }
  220.     else
  221.         init_encodeval(codes, code, pof2len, x);
  222.     code++;
  223.     }
  224.     
  225.     /* chop off LSB to form the half codes */
  226.     code >>= 1;
  227.     pof2len--;
  228.     
  229.     /* create the half codes */
  230.     while(half--) {
  231.     do x++; while(codes[x].inuse == 0);
  232.  
  233.     if (direction == DECODE) {
  234.         codes[x].code = (char)code;
  235.         codes[x].len = (char)pof2len;
  236.     }
  237.     else
  238.         init_encodeval(codes, code, pof2len, x);
  239.     code++;
  240.     }
  241. }
  242.