home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / charsets / csetu.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  8KB  |  191 lines

  1. /*
  2.   csetu.c  --  character-set utility program.
  3.  
  4.   Contains three general-purpose routines, plus a main program to demonstrate
  5.   their use.
  6.  
  7.     invert():   Given a translation table, compute its inverse.
  8.     compose():  Given two translation tables, compute their composition.
  9.     display():  Print a translation table in the desired radix.
  10.  
  11.   F. da Cruz, Columbia University, January 1992
  12. */
  13. #include <stdio.h>
  14.  
  15. char **xargv;                /* Global copy of argv */
  16.  
  17. /* IBM CP437 to CP850, from CDRA */
  18. int
  19. x4385[] = {
  20.   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
  21.  16,  17,  18,  19, 244, 245,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
  22.  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
  23.  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
  24.  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
  25.  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
  26.  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  27. 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
  28. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
  29. 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 189, 156, 190, 158, 159,
  30. 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
  31. 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 155, 157, 191,
  32. 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
  33. 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
  34. 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
  35. 240, 241, 242, 243,  20,  21, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
  36. };
  37.  
  38. /* IBM CP850 to Latin Alphabet 1, from CDRA */
  39. int
  40. x85l1[] = {
  41.   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
  42.  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  28,  27, 127,  29,  30,  31,
  43.  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
  44.  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
  45.  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
  46.  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
  47.  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
  48. 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,  26,
  49. 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197,
  50. 201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 248, 163, 216, 215, 159,
  51. 225, 237, 243, 250, 241, 209, 170, 186, 191, 174, 172, 189, 188, 161, 171, 187,
  52. 155, 156, 157, 144, 151, 193, 194, 192, 169, 135, 128, 131, 133, 162, 165, 147,
  53. 148, 153, 152, 150, 145, 154, 227, 195, 132, 130, 137, 136, 134, 129, 138, 164,
  54. 240, 208, 202, 203, 200, 158, 205, 206, 207, 149, 146, 141, 140, 166, 204, 139,
  55. 211, 223, 212, 210, 245, 213, 181, 254, 222, 218, 219, 217, 253, 221, 175, 180,
  56. 173, 177, 143, 190, 182, 167, 247, 184, 176, 168, 183, 185, 179, 178, 142, 160
  57. };
  58.  
  59. int xl185[256];                /* Latin-1 to CP850 (to be computed) */
  60. int xl143[256];                /* Latin-1 to CP437 (to be computed) */
  61. int x43l1[256];                /* CP437 to Latin-1 (to be computed) */
  62.  
  63. /*
  64.   Compute the inverse of a 256-byte translation table, array c1.
  65.   If the table is not invertible, print a message and exit.
  66.   If it is invertible, put the invertible table in array c2.
  67. */
  68. void
  69. invert(c1, c2) int c1[], c2[]; {
  70.     int i;                /* Loop index */
  71.     int err = 0;            /* Error counter */
  72.  
  73.     for (i = 0; i < 256; i++)        /* Initialize the output array */
  74.       c2[i] = -1;            /*  to all -1's. */
  75.  
  76.     for (i = 0; i < 256; i++) {        /* Compute the inverse. */
  77.     if (c1[i] < 0 || c1[i] > 255) {    /* Check for illegal input values */
  78.         fprintf(stderr,
  79.             "Table contains illegal value %d\n",c1[i]);
  80.         exit(1);
  81.     } else if (c2[c1[i]] == -1) {    /* Check for duplicates. */
  82.         c2[c1[i]] = i & 0xff;    /* This one is ok. */
  83.     } else {            /* Duplicate or missing values mean */
  84.         if (++err == 1) {        /* character set is not invertible. */
  85.         fprintf(stderr,
  86.             "Character set not invertible.\n");
  87.         fprintf(stderr,
  88.             "The following characters appear more than once:\n");
  89.         }
  90.         fprintf(stderr, " %3d\n", i);
  91.     }
  92.     }
  93.     if (err > 0) {            /* Display missing entries, if any */
  94.     fprintf(stderr,
  95.         "The following characters are missing:\n");
  96.     for (i = 0; i < 256; i++)
  97.       if (c2[i] == -1) fprintf(stderr," %3d\n", i);
  98.     exit(1);
  99.     }
  100. }
  101.  
  102. /*
  103.   Given c1, the translation table from character set X to character set Y,
  104.   and c2, the translation table from character set Y to character set Z,
  105.   compute c3, the translation table from character set X to character set Z,
  106.   i.e. the composition of tables c1 and c2.
  107. */
  108. void
  109. compose(c1, c2, c3) int c1[], c2[], c3[]; {
  110.     int i;
  111.     for (i = 0; i < 256; i++) {        /* Check for illegal input values */
  112.     if (c1[i] < 0 || c1[i] > 255 ||
  113.         c2[i] < 0 || c2[i] > 255) {
  114.         fprintf(stderr,"Table contains illegal value %d\n",c1[i]);
  115.         exit(1);
  116.     } else c3[i] = c2[c1[i]];    /* Translate c1 -> c2 -> c3 */
  117.     }
  118. }
  119.  
  120. /*
  121.   Display character set c in the given radix (8, 10, or 16),
  122.   labeled with the given name.
  123. */
  124. void
  125. display(c,radix,name) int c[], radix; char *name; {
  126.     int i, j, k;            /* Loop indices */
  127.     char buf[10];            /* Output string buffer */
  128.     printf("%s\n",name);        /* Print the table name */
  129.     for (i = 0; i < 16; i++)        /* Print the table, each row */
  130.       for (j = 0; j < 16; j++) {    /* and each element in the row */
  131.       k = 16 * i + j;        /* Table index of this item */
  132.       switch (radix) {        /* Use the desired radix */
  133.         case 8:  sprintf(buf,  "%3o", c[k]); break;    /* Octal */
  134.         case 10: sprintf(buf,  "%3d", c[k]); break;    /* Decimal */
  135.         case 16: sprintf(buf," %02X", c[k]); break;    /* Hexadecimal */
  136.         default:
  137.           fprintf(stderr,"display: bad radix\n");
  138.           exit(1);
  139.       }
  140.       if (j == 15)            /* Final item in row */
  141.         printf(k == 255 ?
  142.            "%s\n" :        /* Final item in table */
  143.            "%s,\n", buf);
  144.       else
  145.         printf("%s, ",buf);        /* Item within row */
  146.       }
  147.     printf("\n");            /* Blank line at end */
  148. }
  149.  
  150. void                    /* Usage message */
  151. usage(s1,s2) char *s1, *s2; {
  152.     fprintf(stderr,"%s: %s '%s'\n",xargv[0],s1,s2);
  153.     fprintf(stderr,"usage: %s [ -radix ]\n",xargv[0]);    
  154.     fprintf(stderr,"optional argument is the output radix\n");
  155.     fprintf(stderr,"radix may be 8, 10, or 16, 10 by default\n");
  156.     exit(1);
  157. }
  158.  
  159. void
  160. main(argc,argv) int argc; char *argv[]; {
  161.     int i;                /* Worker */
  162.     int r = 10;                /* Radix for output, default 10 */
  163.  
  164.     xargv = argv;            /* Make global copy */
  165.  
  166.     for (i = 1; i < argc; i++) {    /* Read radix from command line */
  167.     if (*argv[i] != '-') usage("bad option",argv[i]);
  168.     r = atoi(argv[i]+1);
  169.     if (r != 8 && r != 10 && r != 16) usage("bad radix",argv[i]+1);
  170.     }
  171.     if ((i = sizeof(x4385)) != 256 * sizeof (int)) {
  172.     fprintf(stderr,"size of x4385 = %d, should be 256\n",i);
  173.     exit(1);
  174.     }
  175.     if ((i = sizeof(x85l1)) != 256 * sizeof (int)) {
  176.     fprintf(stderr,"size of x85l1 = %d, should be 256\n",i);
  177.     exit(1);
  178.     }
  179.     display(x4385,r,"CP437 to CP850");    /* These are given. */
  180.     display(x85l1,r,"CP850 to Latin-1"); /* Print them. */
  181.  
  182.     invert(x85l1, xl185);        /* Compute Latin-1 to cp850 */
  183.     display(xl185,r,"Latin-1 to CP850"); /* Print it. */
  184.  
  185.     compose(x4385, x85l1, x43l1);    /* Compute cp437-to-latin1 */
  186.     display(x43l1,r,"CP437 to Latin-1"); /* Print it. */
  187.  
  188.     invert(x43l1, xl143);        /* Compute Latin1 to CP437 */
  189.     display(xl143,r,"Latin-1 to CP437"); /* Print it. */
  190. }
  191.