4 * Copyright 2020 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
31 static const void *read_data( unsigned int *pos
, unsigned int size
)
33 const void *ret
= PRD( *pos
, size
);
38 static unsigned short mapchar( const unsigned short *table
, unsigned int len
, unsigned short ch
)
40 unsigned int off
= table
[ch
>> 8] + ((ch
>> 4) & 0x0f);
41 if (off
>= len
) return 0;
42 off
= table
[off
] + (ch
& 0x0f);
43 if (off
>= len
) return 0;
44 return ch
+ table
[off
];
47 static void dump_offset_table( const unsigned short *table
, unsigned int len
)
51 for (i
= 0; i
< 0x10000; i
++)
53 if (!(i
% 16)) printf( "\n%04x:", i
);
54 ch
= mapchar( table
, len
, i
);
55 if (ch
== i
) printf( " ...." );
56 else printf( " %04x", ch
);
65 static const char *get_ctype( const struct ctype
*ctype
)
67 static char buffer
[100];
68 static const char *c1
[] = { "up ", "lo ", "dg ", "sp ", "pt ", "cl ", "bl ", "xd ", "al " };
69 static const char *c2
[] = { " ", "L ", "R ", "EN", "ES", "ET",
70 "AN", "CS", "B ", "S ", "WS", "ON" };
71 static const char *c3
[] = { "ns ", "di ", "vo ", "sy ", "ka ", "hi ", "hw ", "fw ",
72 "id ", "ks ", "lx ", "hi ", "lo ", " ", " ", "al " };
74 strcpy( buffer
, "| " );
75 for (i
= 0; i
< ARRAY_SIZE(c1
); i
++)
76 strcat( buffer
, (ctype
->c1
& (1 << i
)) ? c1
[i
] : "__ " );
77 strcat( buffer
, "| " );
78 strcat( buffer
, ctype
->c2
< ARRAY_SIZE(c2
) ? c2
[ctype
->c2
] : "??" );
79 strcat( buffer
, " | " );
80 for (i
= 0; i
< ARRAY_SIZE(c3
); i
++)
81 strcat( buffer
, (ctype
->c3
& (1 << i
)) ? c3
[i
] : "__ " );
82 strcat( buffer
, "|" );
86 static void dump_ctype_table( const USHORT
*ptr
)
88 const struct ctype
*ctypes
= (const struct ctype
*)(ptr
+ 2);
89 const BYTE
*types
= (const BYTE
*)ptr
+ ptr
[1] + 2;
90 int i
, len
= (ptr
[1] - 2) / sizeof(*ctypes
);
92 printf( " CTYPE1 CTYPE2 CTYPE3\n" );
93 for (i
= 0; i
< 0x10000; i
++)
95 const BYTE
*b
= types
+ ((const WORD
*)types
)[i
>> 8];
96 b
= types
+ ((const WORD
*)b
)[(i
>> 4) & 0x0f] + (i
& 0x0f);
97 if (*b
< len
) printf( "%04x %s\n", i
, get_ctype( ctypes
+ *b
));
98 else printf( "%04x ??? %02x\n", i
, *b
);
103 static void dump_casemap(void)
105 unsigned int pos
= 0, upper_len
, lower_len
;
106 const unsigned short *header
, *upper
, *lower
;
108 if (!(header
= read_data( &pos
, 2 * sizeof(*header
) ))) return;
109 upper_len
= header
[1];
110 if (!(upper
= read_data( &pos
, upper_len
* sizeof(*upper
) )))
112 printf( "Invalid len %04x\n", header
[1] );
115 lower_len
= dump_total_len
/ sizeof(*lower
) - 2 - upper_len
;
116 if (!(lower
= read_data( &pos
, lower_len
* sizeof(*lower
) ))) return;
118 printf( "Magic: %04x\n", header
[0] );
119 printf( "Upper-case table:\n" );
120 dump_offset_table( upper
, upper_len
);
121 printf( "\n\nLower-case table:\n" );
122 dump_offset_table( lower
, lower_len
);
126 static void dump_codepage(void)
128 unsigned int i
, j
, uni2cp_offset
, pos
= 0;
129 const unsigned short *header
, *ptr
;
131 if (!(header
= read_data( &pos
, 13 * sizeof(*header
) ))) return;
132 printf( "Codepage: %03u\n", header
[1] );
133 printf( "Char size: %u\n", header
[2] );
134 printf( "Default char A: %04x / %04x\n", header
[3], header
[5] );
135 printf( "Default char W: %04x / %04x\n", header
[4], header
[6] );
138 printf( "Lead bytes: " );
139 for (i
= 0; i
< 12; i
++)
141 unsigned char val
= ((unsigned char *)(header
+ 7))[i
];
143 printf( "%c%02x", (i
% 2) ? '-' : ' ', val
);
147 printf( "\nCharacter map:\n" );
148 pos
= header
[0] * sizeof(*ptr
);
149 if (!(ptr
= read_data( &pos
, sizeof(*ptr
) ))) return;
150 uni2cp_offset
= pos
/ sizeof(*ptr
) + *ptr
;
151 if (!(ptr
= read_data( &pos
, 256 * sizeof(*ptr
) ))) return;
152 for (i
= 0; i
< 256; i
++)
154 if (!(i
% 16)) printf( "\n%02x:", i
);
155 printf( " %04x", ptr
[i
] );
158 if (!(ptr
= read_data( &pos
, sizeof(*ptr
) ))) return;
161 if (!(ptr
= read_data( &pos
, 256 * sizeof(*ptr
) ))) return;
162 printf( "\nGlyph table:\n" );
163 for (i
= 0; i
< 256; i
++)
165 if (!(i
% 16)) printf( "\n%02x:", i
);
166 printf( " %04x", ptr
[i
] );
170 if (!(ptr
= read_data( &pos
, sizeof(*ptr
) ))) return;
173 if (!(ptr
= read_data( &pos
, (uni2cp_offset
- pos
) * sizeof(*ptr
) ))) return;
174 for (i
= 0; i
< 256; i
++)
176 if (!ptr
[i
] || ptr
[i
] > pos
- 256) continue;
177 for (j
= 0; j
< 256; j
++)
179 if (!(j
% 16)) printf( "\n%02x%02x:", i
, j
);
180 printf( " %04x", ptr
[ptr
[i
] + j
] );
185 printf( "\nUnicode table:\n" );
186 pos
= uni2cp_offset
* sizeof(*ptr
);
189 if (!(ptr
= read_data( &pos
, 65536 * sizeof(*ptr
) ))) return;
190 for (i
= 0; i
< 65536; i
++)
192 if (!(i
% 16)) printf( "\n%04x:", i
);
193 printf( " %04x", ptr
[i
] );
199 const unsigned char *uni2cp
;
200 if (!(uni2cp
= read_data( &pos
, 65536 ))) return;
201 for (i
= 0; i
< 65536; i
++)
203 if (!(i
% 16)) printf( "\n%04x:", i
);
204 printf( " %02x", uni2cp
[i
] );
213 WCHAR name
[13]; /* 00 file name */
214 USHORT checksum
[3]; /* 1a checksum? */
215 USHORT version
[4]; /* 20 Unicode version */
216 USHORT form
; /* 28 normalization form */
217 USHORT len_factor
; /* 2a factor for length estimates */
218 USHORT unknown1
; /* 2c */
219 USHORT decomp_size
; /* 2e decomposition hash size */
220 USHORT comp_size
; /* 30 composition hash size */
221 USHORT unknown2
; /* 32 */
222 USHORT classes
; /* 34 combining classes table offset */
223 USHORT props_level1
; /* 36 char properties table level 1 offset */
224 USHORT props_level2
; /* 38 char properties table level 2 offset */
225 USHORT decomp_hash
; /* 3a decomposition hash table offset */
226 USHORT decomp_map
; /* 3c decomposition character map table offset */
227 USHORT decomp_seq
; /* 3e decomposition character sequences offset */
228 USHORT comp_hash
; /* 40 composition hash table offset */
229 USHORT comp_seq
; /* 42 composition character sequences offset */
232 static int offset_scale
= 1; /* older versions use byte offsets */
234 #define GET_TABLE(info,table) ((const void *)((const BYTE *)info + (info->table * offset_scale)))
236 static unsigned int get_utf16( const WCHAR
*str
)
238 if (str
[0] >= 0xd800 && str
[0] <= 0xdbff &&
239 str
[1] >= 0xdc00 && str
[1] <= 0xdfff)
240 return 0x10000 + ((str
[0] & 0x3ff) << 10) + (str
[1] & 0x3ff);
244 static BYTE
rol( BYTE val
, BYTE count
)
246 return (val
<< count
) | (val
>> (8 - count
));
249 static unsigned char get_char_props( const struct norm_table
*info
, unsigned int ch
)
251 const BYTE
*level1
= GET_TABLE( info
, props_level1
);
252 const BYTE
*level2
= GET_TABLE( info
, props_level2
);
253 BYTE off
= level1
[ch
/ 128];
255 if (!off
|| off
>= 0xfb) return rol( off
, 5 );
256 return level2
[(off
- 1) * 128 + ch
% 128];
259 static const WCHAR
*get_decomposition( const struct norm_table
*info
,
260 unsigned int ch
, unsigned int *ret_len
)
262 const USHORT
*hash_table
= GET_TABLE( info
, decomp_hash
);
263 const WCHAR
*seq
= GET_TABLE(info
, decomp_seq
);
265 unsigned int i
, pos
, end
, len
, hash
;
267 *ret_len
= 1 + (ch
>= 0x10000);
268 if (!info
->decomp_size
) return NULL
;
269 hash
= ch
% info
->decomp_size
;
270 pos
= hash_table
[hash
];
273 if (get_char_props( info
, ch
) != 0xbf) return NULL
;
274 ret
= seq
+ (pos
& 0x1fff);
279 const struct { WCHAR src
; USHORT dst
; } *pairs
= GET_TABLE( info
, decomp_map
);
281 /* find the end of the hash bucket */
282 for (i
= hash
+ 1; i
< info
->decomp_size
; i
++) if (!(hash_table
[i
] >> 13)) break;
283 if (i
< info
->decomp_size
) end
= hash_table
[i
];
284 else for (end
= pos
; pairs
[end
].src
; end
++) ;
286 for ( ; pos
< end
; pos
++)
288 if (pairs
[pos
].src
!= (WCHAR
)ch
) continue;
289 ret
= seq
+ (pairs
[pos
].dst
& 0x1fff);
290 len
= pairs
[pos
].dst
>> 13;
293 if (pos
>= end
) return NULL
;
296 if (len
== 7) while (ret
[len
]) len
++;
301 static int cmp_compos( const void *a
, const void *b
)
303 int ret
= ((unsigned int *)a
)[0] - ((unsigned int *)b
)[0];
304 if (!ret
) ret
= ((unsigned int *)a
)[1] - ((unsigned int *)b
)[1];
308 static void dump_norm(void)
310 const struct norm_table
*info
;
315 if (!(info
= PRD( 0, sizeof(*info
) ))) return;
316 for (i
= 0; i
< sizeof(name
); i
++) name
[i
] = info
->name
[i
];
317 printf( "Name: %s\n", name
);
320 case 1: printf( "Form: NFC\n" ); break;
321 case 2: printf( "Form: NFD\n" ); break;
322 case 5: printf( "Form: NFKC\n" ); break;
323 case 6: printf( "Form: NFKD\n" ); break;
324 case 13: printf( "Form: IDNA\n" ); break;
325 default: printf( "Form: %u\n", info
->form
); break;
327 printf( "Version: %u.%u.%u\n", info
->version
[0], info
->version
[1], info
->version
[2] );
328 printf( "Factor: %u\n", info
->len_factor
);
330 if (info
->classes
== sizeof(*info
) / 2) offset_scale
= 2;
331 classes
= GET_TABLE( info
, classes
);
333 printf( "\nCharacter classes:\n" );
334 for (i
= 0; i
< 0x110000; i
++)
336 BYTE flags
= get_char_props( info
, i
);
338 if (!(i
% 16)) printf( "\n%06x:", i
);
339 if (!flags
|| (flags
& 0x3f) == 0x3f)
341 static const char *flagstr
[4] = { ".....", "Undef", "QC=No", "Inval" };
342 printf( " %s", flagstr
[flags
>> 6] );
346 static const char flagschar
[4] = ".+*M";
347 BYTE
class = classes
[flags
& 0x3f];
348 printf( " %c.%03u", flagschar
[flags
>> 6], class );
352 printf( "\n\nDecompositions:\n\n" );
353 for (i
= 0; i
< 0x110000; i
++)
356 const WCHAR
*decomp
= get_decomposition( info
, i
, &len
);
357 if (!decomp
) continue;
358 printf( "%04x ->", i
);
359 for (j
= 0; j
< len
; j
++)
361 unsigned int ch
= get_utf16( decomp
+ j
);
362 printf( " %04x", ch
);
363 if (ch
>= 0x10000) j
++;
369 unsigned int pos
, len
= (dump_total_len
- info
->comp_seq
* offset_scale
) / sizeof(WCHAR
);
370 const WCHAR
*seq
= GET_TABLE( info
, comp_seq
);
371 unsigned int *map
= malloc( len
* sizeof(*map
) );
373 printf( "\nCompositions:\n\n" );
375 /* ignore hash table, simply dump all the sequences */
376 for (i
= pos
= 0; i
< len
; pos
+= 3)
378 map
[pos
] = get_utf16( seq
+ i
);
379 i
+= 1 + (map
[pos
] >= 0x10000);
380 map
[pos
+1] = get_utf16( seq
+ i
);
381 i
+= 1 + (map
[pos
+1] >= 0x10000);
382 map
[pos
+2] = get_utf16( seq
+ i
);
383 i
+= 1 + (map
[pos
+2] >= 0x10000);
385 qsort( map
, pos
/ 3, 3 * sizeof(*map
), cmp_compos
);
386 for (i
= 0; i
< pos
; i
+= 3) printf( "%04x %04x -> %04x\n", map
[i
], map
[i
+ 1], map
[i
+ 2] );
395 GUID id
; /* sort GUID */
396 DWORD flags
; /* flags */
397 DWORD compr
; /* offset to compression table */
398 DWORD except
; /* exception table offset in sortkey table */
399 DWORD ling_except
; /* exception table offset for linguistic casing */
400 DWORD casemap
; /* linguistic casemap table offset */
403 #define FLAG_HAS_3_BYTE_WEIGHTS 0x01
404 #define FLAG_REVERSEDIACRITICS 0x10
405 #define FLAG_DOUBLECOMPRESSION 0x20
406 #define FLAG_INVERSECASING 0x40
417 WCHAR minchar
, maxchar
;
423 struct compression compr
;
427 static const char *get_sortkey( DWORD key
)
429 static char buffer
[16];
430 if (!key
) return "....";
431 if ((WORD
)key
== 0x200)
432 sprintf( buffer
, "expand %04x", key
>> 16 );
434 sprintf( buffer
, "%u.%u.%u.%u", (BYTE
)(key
>> 8), (BYTE
)key
, (BYTE
)(key
>> 16), (BYTE
)(key
>> 24) );
438 static const void *dump_expansions( const DWORD
*ptr
)
440 DWORD i
, count
= *ptr
++;
442 printf( "\nExpansions: (count=%04x)\n\n", count
);
443 for (i
= 0; i
< count
; i
++)
445 const WCHAR
*p
= (const WCHAR
*)(ptr
+ i
);
446 printf( " %04x: %04x %04x\n", i
, p
[0], p
[1] );
451 static void dump_exceptions( const DWORD
*sortkeys
, DWORD offset
)
454 const DWORD
*table
= sortkeys
+ offset
;
456 for (i
= 0; i
< 0x100; i
++)
458 if (table
[i
] == i
* 0x100) continue;
459 for (j
= 0; j
< 0x100; j
++)
461 if (sortkeys
[table
[i
] + j
] == sortkeys
[i
* 0x100 + j
]) continue;
462 printf( " %04x: %s\n", i
* 0x100 + j
, get_sortkey( sortkeys
[table
[i
] + j
] ));
467 static const void *dump_compression( const struct compression
*compr
, const WCHAR
*table
)
470 const WCHAR
*p
= table
+ compr
->offset
;
472 printf( " min=%04x max=%04x counts=%u,%u,%u,%u,%u,%u,%u,%u\n",
473 compr
->minchar
, compr
->maxchar
,
474 compr
->len
[0], compr
->len
[1], compr
->len
[2], compr
->len
[3],
475 compr
->len
[4], compr
->len
[5], compr
->len
[6], compr
->len
[7] );
476 for (i
= 0; i
< 8; i
++)
478 for (j
= 0; j
< compr
->len
[i
]; j
++)
481 for (k
= 0; k
< i
+ 2; k
++) printf( " %04x", *p
++ );
482 p
= (const WCHAR
*)(((ULONG_PTR
)p
+ 3) & ~3);
483 printf( " -> %s\n", get_sortkey( *(const DWORD
*)p
));
490 static const void *dump_multiple_weights( const DWORD
*ptr
)
492 int i
, count
= *ptr
++;
495 printf( "\nMultiple weights: (count=%u)\n\n", count
);
496 p
= (const WCHAR
*)ptr
;
497 for (i
= 0; i
< count
; i
++)
500 BYTE count
= p
[i
] >> 8;
501 printf( "%u - %u\n", weight
, weight
+ count
);
503 return ptr
+ (count
+ 1) / 2;
506 static void dump_sort( int old_version
)
516 const struct compression
*compr
;
517 const struct sortguid
*guids
;
518 const struct comprlang
*comprlangs
;
519 const struct language_id
*language_ids
= NULL
;
520 const WORD
*casemaps
, *map
;
521 const DWORD
*sortkeys
, *ptr
;
522 const WCHAR
*p
= NULL
;
524 int nb_casemaps
= 0, casemap_offsets
[16];
526 if (!(header
= PRD( 0, sizeof(*header
) ))) return;
528 if (!(sortkeys
= PRD( header
->sortkeys
, header
->casemaps
- header
->sortkeys
))) return;
529 printf( "\nSort keys:\n" );
530 for (i
= 0; i
< 0x10000; i
++)
532 if (!(i
% 8)) printf( "\n%04x:", i
);
533 printf( " %16s", get_sortkey( sortkeys
[i
] ));
537 size
= (header
->ctypes
- header
->casemaps
) / sizeof(*casemaps
);
538 if (!(casemaps
= PRD( header
->casemaps
, size
* sizeof(*casemaps
) ))) return;
542 ptr
= (const DWORD
*)casemaps
;
544 language_ids
= (const struct language_id
*)ptr
;
545 casemaps
= (const WORD
*)(language_ids
+ len
);
550 const WORD
*upper
= map
+ 2;
551 const WORD
*lower
= map
+ 2 + map
[1];
552 const WORD
*end
= map
+ map
[1] + 1 + map
[map
[1] + 1];
554 if (map
[0] != 1) break;
555 printf( "\nCase mapping table %u:\n", nb_casemaps
);
556 casemap_offsets
[nb_casemaps
++] = map
- casemaps
;
557 for (j
= 0; j
< len
; j
++)
559 if (language_ids
[j
].offset
!= map
- casemaps
) continue;
560 printf( "Language: %s\n", get_unicode_str( language_ids
[j
].name
, -1 ));
563 printf( "\nUpper-case table:\n" );
564 dump_offset_table( upper
, lower
- upper
);
565 printf( "\n\nLower-case table:\n" );
566 dump_offset_table( lower
, end
- lower
);
572 if (!(p
= PRD( header
->ctypes
, header
->sortids
- header
->ctypes
))) return;
573 printf( "\nCTYPE table:\n\n" );
574 dump_ctype_table( p
);
576 printf( "\nSort tables:\n\n" );
577 size
= (dump_total_len
- header
->sortids
) / sizeof(*ptr
);
578 if (!(ptr
= PRD( header
->sortids
, size
* sizeof(*ptr
) ))) return;
583 for (i
= 0; i
< len
; i
++, ptr
+= 2) printf( "NLS version: %08x %08x\n", ptr
[0], ptr
[1] );
585 for (i
= 0; i
< len
; i
++, ptr
+= 2) printf( "Defined version: %08x %08x\n", ptr
[0], ptr
[1] );
587 printf( "\nReversed diacritics:\n\n" );
588 for (i
= 0; i
< len
; i
++)
590 const WCHAR
*name
= (const WCHAR
*)ptr
;
591 printf( "%s\n", get_unicode_str( name
, -1 ));
595 printf( "\nDouble compression:\n\n" );
596 for (i
= 0; i
< len
; i
++)
598 const WCHAR
*name
= (const WCHAR
*)ptr
;
599 printf( "%s\n", get_unicode_str( name
, -1 ));
602 ptr
= dump_expansions( ptr
);
604 printf( "\nCompressions:\n" );
606 comprlangs
= (const struct comprlang
*)ptr
;
607 for (i
= 0; i
< size
; i
++)
609 printf( "\n %s\n", get_unicode_str( comprlangs
[i
].name
, -1 ));
610 ptr
= dump_compression( &comprlangs
[i
].compr
, (const WCHAR
*)(comprlangs
+ size
) );
613 ptr
= dump_multiple_weights( ptr
);
616 printf( "\nJamo sort:\n\n" );
617 for (i
= 0; i
< size
; i
++, ptr
+= 2)
619 const struct jamo
{ BYTE val
[5], off
, len
; } *jamo
= (const struct jamo
*)ptr
;
620 printf( "%04x: %02x %02x %02x %02x %02x off=%02x len=%02x\n", 0x1100 + i
, jamo
->val
[0],
621 jamo
->val
[1], jamo
->val
[2], jamo
->val
[3], jamo
->val
[4],
622 jamo
->off
, jamo
->len
);
626 printf( "\nJamo second chars:\n\n" );
627 for (i
= 0; i
< size
; i
++, ptr
+= 2)
629 const struct jamo
{ WORD ch
; BYTE val
[5], len
; } *jamo
= (const struct jamo
*)ptr
;
630 printf( "%02x: %04x: %02x %02x %02x %02x %02x len=%02x\n", i
, jamo
->ch
, jamo
->val
[0],
631 jamo
->val
[1], jamo
->val
[2], jamo
->val
[3], jamo
->val
[4], jamo
->len
);
635 printf( "\nExceptions:\n" );
636 language_ids
= (const struct language_id
*)ptr
;
637 for (i
= 0; i
< size
; i
++)
639 printf( "\n %08x %s\n", language_ids
[i
].offset
, get_unicode_str( language_ids
[i
].name
, -1 ));
640 dump_exceptions( sortkeys
, language_ids
[i
].offset
);
645 int guid_count
= ptr
[1];
646 printf( "NLS version: %08x\n\n", ptr
[0] );
647 printf( "Sort GUIDs:\n\n" );
648 guids
= (const struct sortguid
*)(ptr
+ 2);
649 for (i
= 0; i
< guid_count
; i
++)
651 for (j
= 0; j
< nb_casemaps
; j
++) if (casemap_offsets
[j
] == guids
[i
].casemap
) break;
652 printf( " %s flags=%08x compr=%08x casemap=%d\n", get_guid_str( &guids
[i
].id
),
653 guids
[i
].flags
, guids
[i
].compr
, j
< nb_casemaps
? j
: -1 );
656 ptr
= dump_expansions( (const DWORD
*)(guids
+ guid_count
) );
659 printf( "\nCompressions:\n" );
660 compr
= (const struct compression
*)ptr
;
661 for (i
= 0; i
< size
; i
++)
664 for (j
= 0; j
< guid_count
; j
++)
665 if (guids
[j
].compr
== i
) printf( " %s\n", get_guid_str( &guids
[j
].id
));
666 ptr
= dump_compression( compr
+ i
, (const WCHAR
*)(compr
+ size
) );
669 ptr
= dump_multiple_weights( ptr
);
672 printf( "\nJamo sort:\n\n" );
673 for (i
= 0; i
< size
; i
++)
675 static const WCHAR hangul_chars
[] =
677 0xa960, 0xa961, 0xa962, 0xa963, 0xa964, 0xa965, 0xa966, 0xa967,
678 0xa968, 0xa969, 0xa96a, 0xa96b, 0xa96c, 0xa96d, 0xa96e, 0xa96f,
679 0xa970, 0xa971, 0xa972, 0xa973, 0xa974, 0xa975, 0xa976, 0xa977,
680 0xa978, 0xa979, 0xa97a, 0xa97b, 0xa97c,
681 0xd7b0, 0xd7b1, 0xd7b2, 0xd7b3, 0xd7b4, 0xd7b5, 0xd7b6, 0xd7b7,
682 0xd7b8, 0xd7b9, 0xd7ba, 0xd7bb, 0xd7bc, 0xd7bd, 0xd7be, 0xd7bf,
683 0xd7c0, 0xd7c1, 0xd7c2, 0xd7c3, 0xd7c4, 0xd7c5, 0xd7c6,
684 0xd7cb, 0xd7cc, 0xd7cd, 0xd7ce, 0xd7cf,
685 0xd7d0, 0xd7d1, 0xd7d2, 0xd7d3, 0xd7d4, 0xd7d5, 0xd7d6, 0xd7d7,
686 0xd7d8, 0xd7d9, 0xd7da, 0xd7db, 0xd7dc, 0xd7dd, 0xd7de, 0xd7df,
687 0xd7e0, 0xd7e1, 0xd7e2, 0xd7e3, 0xd7e4, 0xd7e5, 0xd7e6, 0xd7e7,
688 0xd7e8, 0xd7e9, 0xd7ea, 0xd7eb, 0xd7ec, 0xd7ed, 0xd7ee, 0xd7ef,
689 0xd7f0, 0xd7f1, 0xd7f2, 0xd7f3, 0xd7f4, 0xd7f5, 0xd7f6, 0xd7f7,
690 0xd7f8, 0xd7f9, 0xd7fa, 0xd7fb
692 const BYTE
*b
= (const BYTE
*)(ptr
+ 2 * i
);
693 WCHAR wc
= i
< 0x100 ? 0x1100 + i
: hangul_chars
[i
- 0x100];
694 printf( "%04x: %02x %02x %02x %02x %02x\n", wc
, b
[0], b
[1], b
[2], b
[3], b
[4] );
697 printf( "\nExceptions:\n" );
698 for (i
= 0; i
< guid_count
; i
++)
700 if (!guids
[i
].except
) continue;
701 printf( "\n %s\n", get_guid_str( &guids
[i
].id
));
702 dump_exceptions( sortkeys
, guids
[i
].except
);
703 if (!guids
[i
].ling_except
) continue;
704 printf( "\n %s LINGUISTIC_CASING\n", get_guid_str( &guids
[i
].id
));
705 dump_exceptions( sortkeys
, guids
[i
].ling_except
);
713 const char *name
= strrchr( globals
.input_name
, '/' );
715 else name
= globals
.input_name
;
716 if (!strcasecmp( name
, "l_intl.nls" )) return dump_casemap();
717 if (!strncasecmp( name
, "c_", 2 )) return dump_codepage();
718 if (!strncasecmp( name
, "norm", 4 )) return dump_norm();
719 if (!strcasecmp( name
, "sortdefault.nls" )) return dump_sort( 0 );
720 if (!strncasecmp( name
, "sort", 4 )) return dump_sort( 1 );
721 fprintf( stderr
, "Unrecognized file name '%s'\n", globals
.input_name
);
724 enum FileSig
get_kind_nls(void)
726 if (strlen( globals
.input_name
) < 5) return SIG_UNKNOWN
;
727 if (strcasecmp( globals
.input_name
+ strlen(globals
.input_name
) - 4, ".nls" )) return SIG_UNKNOWN
;