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