urlmon: Use wide-char string literals.
[wine.git] / tools / winedump / nls.c
blobe69d11c42cb59ab967637f29c518fa89d4f1bad1
1 /*
2 * Dump a NLS file
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
28 #include "windef.h"
29 #include "winedump.h"
31 static const void *read_data( unsigned int *pos, unsigned int size )
33 const void *ret = PRD( *pos, size );
34 *pos += size;
35 return ret;
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 )
49 int i, ch;
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 );
60 struct ctype
62 WORD c1, c2, c3;
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 " };
73 int i;
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, "|" );
83 return 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 );
100 printf( "\n" );
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] );
113 return;
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 );
123 printf( "\n\n" );
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] );
136 if (header[2] == 2)
138 printf( "Lead bytes: " );
139 for (i = 0; i < 12; i++)
141 unsigned char val = ((unsigned char *)(header + 7))[i];
142 if (!val) break;
143 printf( "%c%02x", (i % 2) ? '-' : ' ', val );
145 printf( "\n" );
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] );
157 printf( "\n" );
158 if (!(ptr = read_data( &pos, sizeof(*ptr) ))) return;
159 if (*ptr == 256)
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] );
168 printf( "\n" );
170 if (!(ptr = read_data( &pos, sizeof(*ptr) ))) return;
171 if (*ptr)
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] );
183 printf( "\n" );
185 printf( "\nUnicode table:\n" );
186 pos = uni2cp_offset * sizeof(*ptr);
187 if (header[2] == 2)
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] );
195 printf( "\n" );
197 else
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] );
206 printf( "\n" );
208 printf( "\n" );
211 struct norm_table
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);
241 return str[0];
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 );
264 const WCHAR *ret;
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];
271 if (pos >> 13)
273 if (get_char_props( info, ch ) != 0xbf) return NULL;
274 ret = seq + (pos & 0x1fff);
275 len = pos >> 13;
277 else
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;
291 break;
293 if (pos >= end) return NULL;
296 if (len == 7) while (ret[len]) len++;
297 *ret_len = len;
298 return ret;
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];
305 return ret;
308 static void dump_norm(void)
310 const struct norm_table *info;
311 const BYTE *classes;
312 unsigned int i;
313 char name[13];
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 );
318 switch (info->form)
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] );
344 else
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++)
355 unsigned int j, len;
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++;
365 printf( "\n" );
367 if (info->comp_size)
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] );
387 free( map );
389 printf( "\n" );
393 struct sortguid
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
408 struct language_id
410 DWORD offset;
411 WCHAR name[32];
414 struct compression
416 DWORD offset;
417 WCHAR minchar, maxchar;
418 WORD len[8];
421 struct comprlang
423 struct compression compr;
424 WCHAR name[32];
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 );
433 else
434 sprintf( buffer, "%u.%u.%u.%u", (BYTE)(key >> 8), (BYTE)key, (BYTE)(key >> 16), (BYTE)(key >> 24) );
435 return buffer;
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] );
448 return ptr + count;
451 static void dump_exceptions( const DWORD *sortkeys, DWORD offset )
453 int i, j;
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 )
469 int i, j, k;
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++)
480 printf( " " );
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 ));
484 p += 2;
487 return p;
490 static const void *dump_multiple_weights( const DWORD *ptr )
492 int i, count = *ptr++;
493 const WCHAR *p;
495 printf( "\nMultiple weights: (count=%u)\n\n", count );
496 p = (const WCHAR *)ptr;
497 for (i = 0; i < count; i++)
499 BYTE weight = p[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 )
508 const struct
510 DWORD sortkeys;
511 DWORD casemaps;
512 DWORD ctypes;
513 DWORD sortids;
514 } *header;
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;
523 int i, j, size, len;
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] ));
535 printf( "\n\n" );
537 size = (header->ctypes - header->casemaps) / sizeof(*casemaps);
538 if (!(casemaps = PRD( header->casemaps, size * sizeof(*casemaps) ))) return;
539 len = 0;
540 if (old_version)
542 ptr = (const DWORD *)casemaps;
543 len = *ptr++;
544 language_ids = (const struct language_id *)ptr;
545 casemaps = (const WORD *)(language_ids + len);
547 map = casemaps;
548 while (size)
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 ));
561 break;
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 );
567 printf( "\n\n" );
568 size -= (end - map);
569 map = end;
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;
580 if (old_version)
582 len = *ptr++;
583 for (i = 0; i < len; i++, ptr += 2) printf( "NLS version: %08x %08x\n", ptr[0], ptr[1] );
584 len = *ptr++;
585 for (i = 0; i < len; i++, ptr += 2) printf( "Defined version: %08x %08x\n", ptr[0], ptr[1] );
586 len = *ptr++;
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 ));
592 ptr += 16;
594 len = *ptr++;
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 ));
600 ptr += 16;
602 ptr = dump_expansions( ptr );
604 printf( "\nCompressions:\n" );
605 size = *ptr++;
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 );
615 size = *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 );
625 size = *ptr++;
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 );
634 size = *ptr++;
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 );
643 else
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) );
658 size = *ptr++;
659 printf( "\nCompressions:\n" );
660 compr = (const struct compression *)ptr;
661 for (i = 0; i < size; i++)
663 printf( "\n" );
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 );
671 size = *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 );
708 printf( "\n" );
711 void nls_dump(void)
713 const char *name = strrchr( globals.input_name, '/' );
714 if (name) 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;
728 return SIG_NLS;