#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
#include <iconv.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
static void mk_data(char *,char *);
char * ME;
int status;
static int flag_check = 0;
static struct {
unsigned int from;
unsigned int u4;
} tbl[0x10000];
void
usage(int status)
{
fprintf(stderr, "Usage: %s from-code\n", ME);
exit(status);
}
void
validate(int i, iconv_t cd, iconv_t cd2, iconv_t cd3)
{
uchar_t source_buf[1024];
uchar_t result_buf[1024];
uchar_t tmp_buf[1024];
const uchar_t * source;
uchar_t * result;
uchar_t * tmp;
size_t source_len;
size_t result_len;
size_t result_len2;
size_t tmp_len;
size_t s;
int j;
ulong_t l;
#ifdef _LITTLE_ENDIAN
#define CHECKWITHFILE \
if( flag_check > 0 ) { \
l = 0U; \
for( j = sizeof (tmp_buf) - tmp_len -1; \
j >= ((i == 0) ? 2: 0); j--) \
l = (l << 8) + ((uint_t)tmp_buf[j]); \
if (l != tbl[i].u4 ) fprintf(stderr, "%x != %x \n", l, tbl[i].u4 ); \
}
#else
#define CHECKWITHFILE \
if( flag_check > 0 ) { \
l = 0U; \
j = ((i == 0) ? 2: 0); \
for(; j < sizeof (tmp_buf) - tmp_len ; j++) \
l = (l << 8) + ((uint_t)tmp_buf[j]); \
if (l != tbl[i].u4 ) fprintf(stderr, "%x != %x \n", l, tbl[i].u4 ); \
}
#endif
#define PRINTUNICODE \
tmp = tmp_buf; \
tmp_len = sizeof (tmp_buf); \
result = result_buf; \
result_len2 = sizeof (result_buf) - result_len; \
s = iconv(cd2, (const char**)&result, &result_len2, (char**)&tmp, &tmp_len); \
if (s != 0) { \
printf(" \n stoped \n"); \
fprintf(stderr, "fail to con_LITTLE_ENDIANvert UTF-8 to Unicode\n"); \
exit (status); \
} \
printf("\t"); \
for( j = 0; j < sizeof (tmp_buf) - tmp_len ; j++) \
printf("%02x", (uchar_t)tmp_buf[j]); \
CHECKWITHFILE
#define COMPARE \
tmp = tmp_buf; \
tmp_len = sizeof (tmp_buf); \
result = result_buf; \
result_len2 = sizeof (result_buf) - result_len; \
s = iconv(cd3, (const char**)&result, &result_len2, (char**)&tmp, &tmp_len); \
if (s != 0) { \
printf(" \n WARNING \n"); \
fprintf(stderr, "fail to convert UTF-8 to Orignal Codeset(%x)\n",\
i); \
fprintf(stderr, "errno=%d %d %d\n", \
errno, \
sizeof (result_buf) - result_len - result_len2, \
result - result_buf); \
exit (status); \
} \
printf("\t"); \
if ((sizeof (tmp_buf) - tmp_len != 1) || \
((uchar_t)tmp_buf[0] != (uchar_t)i )) { \
printf("\t-> 0x%2x \n warning \n", (uchar_t)tmp_buf[0] ); \
fprintf(stderr, " Converting answer is not the same (0x%02x) for (0x%02x)\n", \
(uchar_t)tmp_buf[0], i); \
}
#define DATASIZE 1
source_buf[0] = i;
source = source_buf;
source_len = DATASIZE;
result = result_buf;
result_len = sizeof (result_buf);
s = iconv(cd, (const char**)&source, &source_len, (char**)&result, &result_len);
status = 1;
if (((size_t)(0)) == s) {
if ((source_len != 0) ||
((source - source_buf) != DATASIZE)) {
fprintf(stderr, ": %d %d %d\n",
errno,
source_len,
source - source_buf);
exit(status);
}
printf("0x%02x\t0x", i);
for( j = 0; j < sizeof (result_buf) - result_len ; j++)
printf("%02x", (uchar_t)result_buf[j]);
PRINTUNICODE
COMPARE
printf("\n");
return;
}
status += 1;
if (((size_t)(-1)) == s) {
if (errno == EILSEQ) {
printf("0x%02x EILSEQ\n", i);
return;
}
fprintf(stderr, "Error for source 0x%02x(%d): %d %d %d %d %d\n",
i, i,
errno,
(DATASIZE) - source_len,
source - source_buf,
(sizeof (result_buf)) - result_len,
result - result_buf);
exit(status);
}
status += 1;
exit(status);
}
main(int argc, char ** argv)
{
int r;
char * p;
iconv_t cd;
iconv_t cd2;
iconv_t cd3;
int i, j, k;
char *dir;
ME = basename(argv[0]);
setlocale(LC_ALL, "");
status = 100;
for (j = 1; j < argc; j++) {
if (argv[j][0] != '-')
break;
for (k = 1; ; k++) {
if (argv[j][k] == '\0')
break;
if (argv[j][k] == 'c') {
flag_check = 1;
j++;
if (j >= argc) usage(-1);
dir = argv[j];
continue;
}
}
}
if (j >= argc) usage(-1);
if( flag_check > 0 ) mk_data(dir, argv[j]);
cd = iconv_open("UTF-8", argv[j]);
if (((iconv_t)(-1)) == cd) {
perror("iconv_open");
exit(status);
}
cd2 = iconv_open("UCS-2", "UTF-8");
if (((iconv_t)(-1)) == cd2) {
perror("iconv_open for UTF-8");
exit(status);
}
cd3 = iconv_open(argv[j], "UTF-8");
if (((iconv_t)(-1)) == cd3) {
perror("iconv_open for reverse");
exit(status);
}
for (i = 0; i <= 0xff; i++)
validate(i, cd, cd2, cd3);
status = 200;
r = iconv_close(cd);
if (-1 == r) {
perror("iconv_close");
exit(status);
}
r = iconv_close(cd2);
if (-1 == r) {
perror("iconv_close for UTF-8");
exit(status);
}
return (0);
}
static void
mk_data(char *dir, char* name)
{
register int i, j;
char buf[BUFSIZ], num[100];
unsigned int l, k;
FILE *fd;
char file[BUFSIZ];
sprintf( file, "%s/%s.txt", dir, name);
if ((fd = fopen(file, "r")) == NULL) {
perror("fopen");
exit (-1);
}
while (fgets(buf, BUFSIZ, fd)) {
i = 0;
while (buf[i] && isspace(buf[i]))
i++;
if (buf[i] == '#' || buf[i] == '\0')
continue;
for (j = 0; !isspace(buf[i]); i++, j++)
num[j] = buf[i];
num[j] = '\0';
k = strtol(num, (char **)NULL, 16);
while (isspace(buf[i]))
i++;
if (buf[i] == '#' || buf[i] == '\0')
continue;
for (j = 0; !isspace(buf[i]); i++, j++)
num[j] = buf[i];
num[j] = '\0';
l = strtol(num, (char **)NULL, 16);
tbl[k].u4 = l;
tbl[k].from = k;
}
}