4 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
5 #define SVAL(buf, pos) (CVAL(buf, pos) | CVAL(buf, pos+1)<<8)
7 typedef unsigned short uint16;
8 #define smb_ucs2_t unsigned short
12 #define UNI_XDIGIT 0x8
13 #define UNI_SPACE 0x10
19 } smb_unicode_table_t;
21 smb_unicode_table_t map_table[] = {
22 #include "unicode_map_table.h"
26 static int error_count;
28 /* check if a converted character contains a null */
29 static void check_null(iconv_t cd_in, iconv_t cd_out, smb_ucs2_t uc)
32 int inlen=2, outlen=10;
33 char *p = (char *)&uc;
37 iconv(cd_in, &p, &inlen, &q, &outlen);
48 printf("NULL at pos %d in ucs2 char %04x\n",
54 /* check if a uppercase or lowercase version of a char is longer than
56 static void check_case(iconv_t cd_in, iconv_t cd_out, smb_ucs2_t uc)
59 int inlen=2, outlen=10;
60 char *p = (char *)&uc;
65 iconv(cd_in, &p, &inlen, &q, &outlen);
68 if (len1 == 0) return;
70 uc2 = map_table[uc].upper;
76 iconv(cd_in, &p, &inlen, &q, &outlen);
79 uc2 = map_table[uc].lower;
85 iconv(cd_in, &p, &inlen, &q, &outlen);
88 if (len2 > len1 || len3 > len1) {
89 printf("case expansion for ucs2 char %04x (%d/%d/%d)\n",
90 uc, len1, len2, len3);
96 /* check if a character is C compatible */
97 static void check_compat(iconv_t cd_in, iconv_t cd_out, smb_ucs2_t uc)
104 /* only care about 7 bit chars */
105 if (SVAL(&uc, 0) & 0xFF80) return;
107 inlen = 2; outlen = 10;
110 iconv(cd_in, &p, &inlen, &q, &outlen);
113 printf("ucs2 char %04x not C compatible (len=%d)\n",
118 if (buf[0] != SVAL(&uc, 0)) {
119 printf("ucs2 char %04x not C compatible (c=0x%x)\n",
125 inlen = 1; outlen = 2;
128 iconv(cd_out, &q, &inlen, &p, &outlen);
131 printf("ucs2 char %04x not C compatible (uc2=0x%x len=%d): %s\n",
132 uc, uc2, 2-outlen, strerror(errno));
137 /* check if a character is strchr compatible */
138 static void check_strchr_compat(iconv_t cd_in, iconv_t cd_out, smb_ucs2_t uc)
141 int inlen=2, outlen=10;
143 char *p = (char *)&uc;
146 iconv(cd_in, &p, &inlen, &q, &outlen);
148 if (10 - outlen <= 1) return;
150 for (i=0; i<10-outlen; i++) {
151 if (! (buf[i] & 0x80)) {
152 printf("ucs2 char %04x not strchr compatible\n",
159 int main(int argc, char *argv[])
162 iconv_t cd_in, cd_out;
165 printf("Usage: charset_test <CHARSET>\n");
169 cd_in = iconv_open(argv[1], "UCS-2LE");
170 cd_out = iconv_open("UCS-2LE", argv[1]);
172 if (cd_in == (iconv_t)-1 || cd_out == (iconv_t)-1) {
177 for (i=1;i<0x10000;i++) {
178 iconv(cd_in, NULL, NULL, NULL, NULL);
179 iconv(cd_out, NULL, NULL, NULL, NULL);
180 check_null(cd_in, cd_out, i);
181 check_case(cd_in, cd_out, i);
182 check_compat(cd_in, cd_out, i);
183 /* check_strchr_compat(cd_in, cd_out, i); */
186 printf("%d chars convertible\n", 0x10000 - zero_len);
187 if (error_count == 0) {
188 printf("character set %s OK for Samba\n", argv[1]);
190 printf("%d errors in character set\n", error_count);