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
32 static const void *read_data( unsigned int *pos
, unsigned int size
)
34 const void *ret
= PRD( *pos
, size
);
39 static unsigned short mapchar( const unsigned short *table
, unsigned int len
, unsigned short ch
)
41 unsigned int off
= table
[ch
>> 8] + ((ch
>> 4) & 0x0f);
42 if (off
>= len
) return 0;
43 off
= table
[off
] + (ch
& 0x0f);
44 if (off
>= len
) return 0;
45 return ch
+ table
[off
];
48 static unsigned int mapchar_high( const unsigned short *table
, unsigned int len
, unsigned int ch
)
50 unsigned short ch1
= 0xd800 | ((ch
- 0x10000) >> 10);
51 unsigned short ch2
= 0xdc00 | (ch
& 0x3ff);
52 unsigned int off
= table
[256 + (ch1
- 0xd800)] + ((ch2
>> 5) & 0x1f);
53 if (off
>= len
) return 0;
54 off
= table
[off
] + 2 * (ch2
& 0x1f);
55 if (off
>= len
) return 0;
56 return ch
+ *(UINT
*)&table
[off
];
59 static void dump_offset_table( const unsigned short *table
, unsigned int len
)
63 for (i
= empty
= 0; i
< 0x10000; i
+= 16)
65 for (j
= 0; j
< 16; j
++) if (mapchar( table
, len
, i
+ j
) != i
+ j
) break;
71 if (empty
) printf( "\n[...]" );
73 printf( "\n%04x:", i
);
74 for (j
= 0; j
< 16; j
++)
76 ch
= mapchar( table
, len
, i
+ j
);
77 if (ch
== i
+ j
) printf( " ...." );
78 else printf( " %04x", ch
);
81 if (table
[0] >= 0x500)
83 for (i
= 0x10000; i
< 0x110000; i
+= 16)
85 for (j
= 0; j
< 16; j
++) if (mapchar_high( table
, len
, i
+ j
) != i
+ j
) break;
91 if (empty
) printf( "\n[...]" );
93 printf( "\n%06x:", i
);
94 for (j
= 0; j
< 16; j
++)
96 ch
= mapchar_high( table
, len
, i
+ j
);
97 if (ch
== i
+ j
) printf( " ......" );
98 else printf( " %06x", ch
);
102 if (empty
) printf( "\n[...]" );
110 static const char *get_ctype( const struct ctype
*ctype
)
112 static char buffer
[100];
113 static const char *c1
[] = { "up ", "lo ", "dg ", "sp ", "pt ", "cl ", "bl ", "xd ", "al " , "df "};
114 static const char *c2
[] = { " ", "L ", "R ", "EN", "ES", "ET",
115 "AN", "CS", "B ", "S ", "WS", "ON" };
116 static const char *c3
[] = { "ns ", "di ", "vo ", "sy ", "ka ", "hi ", "hw ", "fw ",
117 "id ", "ks ", "lx ", "hi ", "lo ", " ", " ", "al " };
119 strcpy( buffer
, "| " );
120 for (i
= 0; i
< ARRAY_SIZE(c1
); i
++)
121 strcat( buffer
, (ctype
->c1
& (1 << i
)) ? c1
[i
] : "__ " );
122 strcat( buffer
, "| " );
123 strcat( buffer
, ctype
->c2
< ARRAY_SIZE(c2
) ? c2
[ctype
->c2
] : "??" );
124 strcat( buffer
, " | " );
125 for (i
= 0; i
< ARRAY_SIZE(c3
); i
++)
126 strcat( buffer
, (ctype
->c3
& (1 << i
)) ? c3
[i
] : "__ " );
127 strcat( buffer
, "|" );
131 static void dump_ctype_table( const USHORT
*ptr
)
133 const struct ctype
*ctypes
= (const struct ctype
*)(ptr
+ 2);
134 const BYTE
*types
= (const BYTE
*)ptr
+ ptr
[1] + 2;
135 int i
, len
= (ptr
[1] - 2) / sizeof(*ctypes
);
137 printf( " CTYPE1 CTYPE2 CTYPE3\n" );
138 for (i
= 0; i
< 0x10000; i
++)
140 const BYTE
*b
= types
+ ((const WORD
*)types
)[i
>> 8];
141 b
= types
+ ((const WORD
*)b
)[(i
>> 4) & 0x0f] + (i
& 0x0f);
142 if (*b
< len
) printf( "%04x %s\n", i
, get_ctype( ctypes
+ *b
));
143 else printf( "%04x ??? %02x\n", i
, *b
);
148 static void dump_geo_table( const void *ptr
)
152 WCHAR signature
[4]; /* L"geo" */
171 /* new versions only */
178 struct /* old version */
184 struct /* new version */
192 id
= (const struct id
*)((const BYTE
*)data
+ data
->ids_offset
);
193 printf( "GEOIDs: (count %u)\n\n", data
->nb_ids
);
194 for (i
= 0; i
< data
->nb_ids
; i
++)
196 if (!id
[i
].id
) continue;
197 printf( "%u %5s %5s %s parent=%u lat=%s long=%s uncode=%u dialcode=%u currency=%s %s\n", id
[i
].id
,
198 get_unicode_str( id
[i
].iso2
, -1 ), get_unicode_str( id
[i
].iso3
, -1 ),
199 id
[i
].class == GEOCLASS_NATION
? "nation" : id
[i
].class == GEOCLASS_REGION
? "region" : "???",
200 id
[i
].parent
, get_unicode_str( id
[i
].latitude
, -1 ), get_unicode_str( id
[i
].longitude
, -1 ),
201 id
[i
].uncode
, id
[i
].dialcode
, get_unicode_str( id
[i
].currcode
, -1 ),
202 get_unicode_str( id
[i
].currsymbol
, -1 ));
205 locale
= (const union locale
*)((const BYTE
*)data
+ data
->locales_offset
);
206 printf( "\nIndex: (count %u)\n\n", data
->nb_locales
);
207 for (i
= 0; i
< data
->nb_locales
; i
++)
209 printf( "%-5s -> %u %s\n", get_unicode_str( locale
[i
].new.name
, -1 ),
210 id
[locale
[i
].new.idx
].id
, get_unicode_str( id
[locale
[i
].new.idx
].iso3
, -1 ) );
214 static void dump_casemap(void)
216 unsigned int pos
= 0, upper_len
, lower_len
;
217 const unsigned short *header
, *upper
, *lower
;
219 if (!(header
= read_data( &pos
, 2 * sizeof(*header
) ))) return;
220 upper_len
= header
[1];
221 if (!(upper
= read_data( &pos
, upper_len
* sizeof(*upper
) )))
223 printf( "Invalid len %04x\n", header
[1] );
226 lower_len
= dump_total_len
/ sizeof(*lower
) - 2 - upper_len
;
227 if (!(lower
= read_data( &pos
, lower_len
* sizeof(*lower
) ))) return;
229 printf( "Magic: %04x\n", header
[0] );
230 printf( "Upper-case table:\n" );
231 dump_offset_table( upper
, upper_len
);
232 printf( "\n\nLower-case table:\n" );
233 dump_offset_table( lower
, lower_len
);
237 static void dump_codepage(void)
239 unsigned int i
, j
, uni2cp_offset
, pos
= 0;
240 const unsigned short *header
, *ptr
;
242 if (!(header
= read_data( &pos
, 13 * sizeof(*header
) ))) return;
243 printf( "Codepage: %03u\n", header
[1] );
244 printf( "Char size: %u\n", header
[2] );
245 printf( "Default char A: %04x / %04x\n", header
[3], header
[5] );
246 printf( "Default char W: %04x / %04x\n", header
[4], header
[6] );
249 printf( "Lead bytes: " );
250 for (i
= 0; i
< 12; i
++)
252 unsigned char val
= ((unsigned char *)(header
+ 7))[i
];
254 printf( "%c%02x", (i
% 2) ? '-' : ' ', val
);
258 printf( "\nCharacter map:\n" );
259 pos
= header
[0] * sizeof(*ptr
);
260 if (!(ptr
= read_data( &pos
, sizeof(*ptr
) ))) return;
261 uni2cp_offset
= pos
/ sizeof(*ptr
) + *ptr
;
262 if (!(ptr
= read_data( &pos
, 256 * sizeof(*ptr
) ))) return;
263 for (i
= 0; i
< 256; i
++)
265 if (!(i
% 16)) printf( "\n%02x:", i
);
266 printf( " %04x", ptr
[i
] );
269 if (!(ptr
= read_data( &pos
, sizeof(*ptr
) ))) return;
272 if (!(ptr
= read_data( &pos
, 256 * sizeof(*ptr
) ))) return;
273 printf( "\nGlyph table:\n" );
274 for (i
= 0; i
< 256; i
++)
276 if (!(i
% 16)) printf( "\n%02x:", i
);
277 printf( " %04x", ptr
[i
] );
281 if (!(ptr
= read_data( &pos
, sizeof(*ptr
) ))) return;
284 if (!(ptr
= read_data( &pos
, (uni2cp_offset
- pos
) * sizeof(*ptr
) ))) return;
285 for (i
= 0; i
< 256; i
++)
287 if (!ptr
[i
] || ptr
[i
] > pos
- 256) continue;
288 for (j
= 0; j
< 256; j
++)
290 if (!(j
% 16)) printf( "\n%02x%02x:", i
, j
);
291 printf( " %04x", ptr
[ptr
[i
] + j
] );
296 printf( "\nUnicode table:\n" );
297 pos
= uni2cp_offset
* sizeof(*ptr
);
300 if (!(ptr
= read_data( &pos
, 65536 * sizeof(*ptr
) ))) return;
301 for (i
= 0; i
< 65536; i
++)
303 if (!(i
% 16)) printf( "\n%04x:", i
);
304 printf( " %04x", ptr
[i
] );
310 const unsigned char *uni2cp
;
311 if (!(uni2cp
= read_data( &pos
, 65536 ))) return;
312 for (i
= 0; i
< 65536; i
++)
314 if (!(i
% 16)) printf( "\n%04x:", i
);
315 printf( " %02x", uni2cp
[i
] );
324 WCHAR name
[13]; /* 00 file name */
325 USHORT checksum
[3]; /* 1a checksum? */
326 USHORT version
[4]; /* 20 Unicode version */
327 USHORT form
; /* 28 normalization form */
328 USHORT len_factor
; /* 2a factor for length estimates */
329 USHORT unknown1
; /* 2c */
330 USHORT decomp_size
; /* 2e decomposition hash size */
331 USHORT comp_size
; /* 30 composition hash size */
332 USHORT unknown2
; /* 32 */
333 USHORT classes
; /* 34 combining classes table offset */
334 USHORT props_level1
; /* 36 char properties table level 1 offset */
335 USHORT props_level2
; /* 38 char properties table level 2 offset */
336 USHORT decomp_hash
; /* 3a decomposition hash table offset */
337 USHORT decomp_map
; /* 3c decomposition character map table offset */
338 USHORT decomp_seq
; /* 3e decomposition character sequences offset */
339 USHORT comp_hash
; /* 40 composition hash table offset */
340 USHORT comp_seq
; /* 42 composition character sequences offset */
343 static int offset_scale
= 1; /* older versions use byte offsets */
345 #define GET_TABLE(info,table) ((const void *)((const BYTE *)info + (info->table * offset_scale)))
347 static unsigned int get_utf16( const WCHAR
*str
)
349 if (str
[0] >= 0xd800 && str
[0] <= 0xdbff &&
350 str
[1] >= 0xdc00 && str
[1] <= 0xdfff)
351 return 0x10000 + ((str
[0] & 0x3ff) << 10) + (str
[1] & 0x3ff);
355 static BYTE
rol( BYTE val
, BYTE count
)
357 return (val
<< count
) | (val
>> (8 - count
));
360 static unsigned char get_char_props( const struct norm_table
*info
, unsigned int ch
)
362 const BYTE
*level1
= GET_TABLE( info
, props_level1
);
363 const BYTE
*level2
= GET_TABLE( info
, props_level2
);
364 BYTE off
= level1
[ch
/ 128];
366 if (!off
|| off
>= 0xfb) return rol( off
, 5 );
367 return level2
[(off
- 1) * 128 + ch
% 128];
370 static const WCHAR
*get_decomposition( const struct norm_table
*info
,
371 unsigned int ch
, unsigned int *ret_len
)
373 const USHORT
*hash_table
= GET_TABLE( info
, decomp_hash
);
374 const WCHAR
*seq
= GET_TABLE(info
, decomp_seq
);
376 unsigned int i
, pos
, end
, len
, hash
;
378 *ret_len
= 1 + (ch
>= 0x10000);
379 if (!info
->decomp_size
) return NULL
;
380 hash
= ch
% info
->decomp_size
;
381 pos
= hash_table
[hash
];
384 if (get_char_props( info
, ch
) != 0xbf) return NULL
;
385 ret
= seq
+ (pos
& 0x1fff);
390 const struct { WCHAR src
; USHORT dst
; } *pairs
= GET_TABLE( info
, decomp_map
);
392 /* find the end of the hash bucket */
393 for (i
= hash
+ 1; i
< info
->decomp_size
; i
++) if (!(hash_table
[i
] >> 13)) break;
394 if (i
< info
->decomp_size
) end
= hash_table
[i
];
395 else for (end
= pos
; pairs
[end
].src
; end
++) ;
397 for ( ; pos
< end
; pos
++)
399 if (pairs
[pos
].src
!= (WCHAR
)ch
) continue;
400 ret
= seq
+ (pairs
[pos
].dst
& 0x1fff);
401 len
= pairs
[pos
].dst
>> 13;
404 if (pos
>= end
) return NULL
;
407 if (len
== 7) while (ret
[len
]) len
++;
412 static int cmp_compos( const void *a
, const void *b
)
414 int ret
= ((unsigned int *)a
)[0] - ((unsigned int *)b
)[0];
415 if (!ret
) ret
= ((unsigned int *)a
)[1] - ((unsigned int *)b
)[1];
419 static void dump_norm(void)
421 const struct norm_table
*info
;
426 if (!(info
= PRD( 0, sizeof(*info
) ))) return;
427 for (i
= 0; i
< sizeof(name
); i
++) name
[i
] = info
->name
[i
];
428 printf( "Name: %s\n", name
);
431 case 1: printf( "Form: NFC\n" ); break;
432 case 2: printf( "Form: NFD\n" ); break;
433 case 5: printf( "Form: NFKC\n" ); break;
434 case 6: printf( "Form: NFKD\n" ); break;
435 case 13: printf( "Form: IDNA\n" ); break;
436 default: printf( "Form: %u\n", info
->form
); break;
438 printf( "Version: %u.%u.%u\n", info
->version
[0], info
->version
[1], info
->version
[2] );
439 printf( "Factor: %u\n", info
->len_factor
);
441 if (info
->classes
== sizeof(*info
) / 2) offset_scale
= 2;
442 classes
= GET_TABLE( info
, classes
);
444 printf( "\nCharacter classes:\n" );
445 for (i
= 0; i
< 0x110000; i
++)
447 BYTE flags
= get_char_props( info
, i
);
449 if (!(i
% 16)) printf( "\n%06x:", i
);
450 if (!flags
|| (flags
& 0x3f) == 0x3f)
452 static const char *flagstr
[4] = { ".....", "Undef", "QC=No", "Inval" };
453 printf( " %s", flagstr
[flags
>> 6] );
457 static const char flagschar
[4] = ".+*M";
458 BYTE
class = classes
[flags
& 0x3f];
459 printf( " %c.%03u", flagschar
[flags
>> 6], class );
463 printf( "\n\nDecompositions:\n\n" );
464 for (i
= 0; i
< 0x110000; i
++)
467 const WCHAR
*decomp
= get_decomposition( info
, i
, &len
);
468 if (!decomp
) continue;
469 printf( "%04x ->", i
);
470 for (j
= 0; j
< len
; j
++)
472 unsigned int ch
= get_utf16( decomp
+ j
);
473 printf( " %04x", ch
);
474 if (ch
>= 0x10000) j
++;
480 unsigned int pos
, len
= (dump_total_len
- info
->comp_seq
* offset_scale
) / sizeof(WCHAR
);
481 const WCHAR
*seq
= GET_TABLE( info
, comp_seq
);
482 unsigned int *map
= xmalloc( len
* sizeof(*map
) );
484 printf( "\nCompositions:\n\n" );
486 /* ignore hash table, simply dump all the sequences */
487 for (i
= pos
= 0; i
< len
; pos
+= 3)
489 map
[pos
] = get_utf16( seq
+ i
);
490 i
+= 1 + (map
[pos
] >= 0x10000);
491 map
[pos
+1] = get_utf16( seq
+ i
);
492 i
+= 1 + (map
[pos
+1] >= 0x10000);
493 map
[pos
+2] = get_utf16( seq
+ i
);
494 i
+= 1 + (map
[pos
+2] >= 0x10000);
496 qsort( map
, pos
/ 3, 3 * sizeof(*map
), cmp_compos
);
497 for (i
= 0; i
< pos
; i
+= 3) printf( "%04x %04x -> %04x\n", map
[i
], map
[i
+ 1], map
[i
+ 2] );
506 GUID id
; /* sort GUID */
507 UINT flags
; /* flags */
508 UINT compr
; /* offset to compression table */
509 UINT except
; /* exception table offset in sortkey table */
510 UINT ling_except
; /* exception table offset for linguistic casing */
511 UINT casemap
; /* linguistic casemap table offset */
514 #define FLAG_HAS_3_BYTE_WEIGHTS 0x01
515 #define FLAG_REVERSEDIACRITICS 0x10
516 #define FLAG_DOUBLECOMPRESSION 0x20
517 #define FLAG_INVERSECASING 0x40
528 WCHAR minchar
, maxchar
;
534 struct compression compr
;
538 static const char *get_sortkey( UINT key
)
540 static char buffer
[16];
541 if (!key
) return "....";
542 if ((WORD
)key
== 0x200)
543 sprintf( buffer
, "expand %04x", key
>> 16 );
545 sprintf( buffer
, "%u.%u.%u.%u", (BYTE
)(key
>> 8), (BYTE
)key
, (BYTE
)(key
>> 16), (BYTE
)(key
>> 24) );
549 static const void *dump_expansions( const UINT
*ptr
)
551 UINT i
, count
= *ptr
++;
553 printf( "\nExpansions: (count=%04x)\n\n", count
);
554 for (i
= 0; i
< count
; i
++)
556 const WCHAR
*p
= (const WCHAR
*)(ptr
+ i
);
557 printf( " %04x: %04x %04x\n", i
, p
[0], p
[1] );
562 static void dump_exceptions( const UINT
*sortkeys
, DWORD offset
)
565 const UINT
*table
= sortkeys
+ offset
;
567 for (i
= 0; i
< 0x100; i
++)
569 if (table
[i
] == i
* 0x100) continue;
570 for (j
= 0; j
< 0x100; j
++)
572 if (sortkeys
[table
[i
] + j
] == sortkeys
[i
* 0x100 + j
]) continue;
573 printf( " %04x: %s\n", i
* 0x100 + j
, get_sortkey( sortkeys
[table
[i
] + j
] ));
578 static const void *dump_compression( const struct compression
*compr
, const WCHAR
*table
)
581 const WCHAR
*p
= table
+ compr
->offset
;
583 printf( " min=%04x max=%04x counts=%u,%u,%u,%u,%u,%u,%u,%u\n",
584 compr
->minchar
, compr
->maxchar
,
585 compr
->len
[0], compr
->len
[1], compr
->len
[2], compr
->len
[3],
586 compr
->len
[4], compr
->len
[5], compr
->len
[6], compr
->len
[7] );
587 for (i
= 0; i
< 8; i
++)
589 for (j
= 0; j
< compr
->len
[i
]; j
++)
592 for (k
= 0; k
< i
+ 2; k
++) printf( " %04x", *p
++ );
593 p
= (const WCHAR
*)(((ULONG_PTR
)p
+ 3) & ~3);
594 printf( " -> %s\n", get_sortkey( *(const DWORD
*)p
));
601 static const void *dump_multiple_weights( const UINT
*ptr
)
603 UINT i
, count
= *ptr
++;
606 printf( "\nMultiple weights: (count=%u)\n\n", count
);
607 p
= (const WCHAR
*)ptr
;
608 for (i
= 0; i
< count
; i
++)
611 BYTE count
= p
[i
] >> 8;
612 printf( "%u - %u\n", weight
, weight
+ count
);
614 return ptr
+ (count
+ 1) / 2;
617 static void dump_sort( int old_version
)
627 const struct compression
*compr
;
628 const struct sortguid
*guids
;
629 const struct comprlang
*comprlangs
;
630 const struct language_id
*language_ids
= NULL
;
631 const WORD
*casemaps
, *map
;
632 const UINT
*sortkeys
, *ptr
;
633 const WCHAR
*p
= NULL
;
635 int nb_casemaps
= 0, casemap_offsets
[16];
637 if (!(header
= PRD( 0, sizeof(*header
) ))) return;
639 if (!(sortkeys
= PRD( header
->sortkeys
, header
->casemaps
- header
->sortkeys
))) return;
640 printf( "\nSort keys:\n" );
641 for (i
= 0; i
< 0x10000; i
++)
643 if (!(i
% 8)) printf( "\n%04x:", i
);
644 printf( " %16s", get_sortkey( sortkeys
[i
] ));
648 size
= (header
->ctypes
- header
->casemaps
) / sizeof(*casemaps
);
649 if (!(casemaps
= PRD( header
->casemaps
, size
* sizeof(*casemaps
) ))) return;
653 ptr
= (const UINT
*)casemaps
;
655 language_ids
= (const struct language_id
*)ptr
;
656 casemaps
= (const WORD
*)(language_ids
+ len
);
661 const WORD
*upper
= map
+ 2;
662 const WORD
*lower
= map
+ 2 + map
[1];
663 const WORD
*end
= map
+ map
[1] + 1 + map
[map
[1] + 1];
665 if (map
[0] != 1) break;
666 printf( "\nCase mapping table %u:\n", nb_casemaps
);
667 casemap_offsets
[nb_casemaps
++] = map
- casemaps
;
668 for (j
= 0; j
< len
; j
++)
670 if (language_ids
[j
].offset
!= map
- casemaps
) continue;
671 printf( "Language: %s\n", get_unicode_str( language_ids
[j
].name
, -1 ));
674 printf( "\nUpper-case table:\n" );
675 dump_offset_table( upper
, lower
- upper
);
676 printf( "\n\nLower-case table:\n" );
677 dump_offset_table( lower
, end
- lower
);
683 if (!(p
= PRD( header
->ctypes
, header
->sortids
- header
->ctypes
))) return;
684 printf( "\nCTYPE table:\n\n" );
685 dump_ctype_table( p
);
687 printf( "\nSort tables:\n\n" );
688 size
= (dump_total_len
- header
->sortids
) / sizeof(*ptr
);
689 if (!(ptr
= PRD( header
->sortids
, size
* sizeof(*ptr
) ))) return;
694 for (i
= 0; i
< len
; i
++, ptr
+= 2) printf( "NLS version: %08x %08x\n", ptr
[0], ptr
[1] );
696 for (i
= 0; i
< len
; i
++, ptr
+= 2) printf( "Defined version: %08x %08x\n", ptr
[0], ptr
[1] );
698 printf( "\nReversed diacritics:\n\n" );
699 for (i
= 0; i
< len
; i
++)
701 const WCHAR
*name
= (const WCHAR
*)ptr
;
702 printf( "%s\n", get_unicode_str( name
, -1 ));
706 printf( "\nDouble compression:\n\n" );
707 for (i
= 0; i
< len
; i
++)
709 const WCHAR
*name
= (const WCHAR
*)ptr
;
710 printf( "%s\n", get_unicode_str( name
, -1 ));
713 ptr
= dump_expansions( ptr
);
715 printf( "\nCompressions:\n" );
717 comprlangs
= (const struct comprlang
*)ptr
;
718 for (i
= 0; i
< size
; i
++)
720 printf( "\n %s\n", get_unicode_str( comprlangs
[i
].name
, -1 ));
721 ptr
= dump_compression( &comprlangs
[i
].compr
, (const WCHAR
*)(comprlangs
+ size
) );
724 ptr
= dump_multiple_weights( ptr
);
727 printf( "\nJamo sort:\n\n" );
728 for (i
= 0; i
< size
; i
++, ptr
+= 2)
730 const struct jamo
{ BYTE val
[5], off
, len
; } *jamo
= (const struct jamo
*)ptr
;
731 printf( "%04x: %02x %02x %02x %02x %02x off=%02x len=%02x\n", 0x1100 + i
, jamo
->val
[0],
732 jamo
->val
[1], jamo
->val
[2], jamo
->val
[3], jamo
->val
[4],
733 jamo
->off
, jamo
->len
);
737 printf( "\nJamo second chars:\n\n" );
738 for (i
= 0; i
< size
; i
++, ptr
+= 2)
740 const struct jamo
{ WORD ch
; BYTE val
[5], len
; } *jamo
= (const struct jamo
*)ptr
;
741 printf( "%02x: %04x: %02x %02x %02x %02x %02x len=%02x\n", i
, jamo
->ch
, jamo
->val
[0],
742 jamo
->val
[1], jamo
->val
[2], jamo
->val
[3], jamo
->val
[4], jamo
->len
);
746 printf( "\nExceptions:\n" );
747 language_ids
= (const struct language_id
*)ptr
;
748 for (i
= 0; i
< size
; i
++)
750 printf( "\n %08x %s\n", language_ids
[i
].offset
, get_unicode_str( language_ids
[i
].name
, -1 ));
751 dump_exceptions( sortkeys
, language_ids
[i
].offset
);
756 int guid_count
= ptr
[1];
757 printf( "NLS version: %08x\n\n", ptr
[0] );
758 printf( "Sort GUIDs:\n\n" );
759 guids
= (const struct sortguid
*)(ptr
+ 2);
760 for (i
= 0; i
< guid_count
; i
++)
762 for (j
= 0; j
< nb_casemaps
; j
++) if (casemap_offsets
[j
] == guids
[i
].casemap
) break;
763 printf( " %s flags=%08x compr=%08x casemap=%d\n", get_guid_str( &guids
[i
].id
),
764 guids
[i
].flags
, guids
[i
].compr
, j
< nb_casemaps
? j
: -1 );
767 ptr
= dump_expansions( (const UINT
*)(guids
+ guid_count
) );
770 printf( "\nCompressions:\n" );
771 compr
= (const struct compression
*)ptr
;
772 for (i
= 0; i
< size
; i
++)
775 for (j
= 0; j
< guid_count
; j
++)
776 if (guids
[j
].compr
== i
) printf( " %s\n", get_guid_str( &guids
[j
].id
));
777 ptr
= dump_compression( compr
+ i
, (const WCHAR
*)(compr
+ size
) );
780 ptr
= dump_multiple_weights( ptr
);
783 printf( "\nJamo sort:\n\n" );
784 for (i
= 0; i
< size
; i
++)
786 static const WCHAR hangul_chars
[] =
788 0xa960, 0xa961, 0xa962, 0xa963, 0xa964, 0xa965, 0xa966, 0xa967,
789 0xa968, 0xa969, 0xa96a, 0xa96b, 0xa96c, 0xa96d, 0xa96e, 0xa96f,
790 0xa970, 0xa971, 0xa972, 0xa973, 0xa974, 0xa975, 0xa976, 0xa977,
791 0xa978, 0xa979, 0xa97a, 0xa97b, 0xa97c,
792 0xd7b0, 0xd7b1, 0xd7b2, 0xd7b3, 0xd7b4, 0xd7b5, 0xd7b6, 0xd7b7,
793 0xd7b8, 0xd7b9, 0xd7ba, 0xd7bb, 0xd7bc, 0xd7bd, 0xd7be, 0xd7bf,
794 0xd7c0, 0xd7c1, 0xd7c2, 0xd7c3, 0xd7c4, 0xd7c5, 0xd7c6,
795 0xd7cb, 0xd7cc, 0xd7cd, 0xd7ce, 0xd7cf,
796 0xd7d0, 0xd7d1, 0xd7d2, 0xd7d3, 0xd7d4, 0xd7d5, 0xd7d6, 0xd7d7,
797 0xd7d8, 0xd7d9, 0xd7da, 0xd7db, 0xd7dc, 0xd7dd, 0xd7de, 0xd7df,
798 0xd7e0, 0xd7e1, 0xd7e2, 0xd7e3, 0xd7e4, 0xd7e5, 0xd7e6, 0xd7e7,
799 0xd7e8, 0xd7e9, 0xd7ea, 0xd7eb, 0xd7ec, 0xd7ed, 0xd7ee, 0xd7ef,
800 0xd7f0, 0xd7f1, 0xd7f2, 0xd7f3, 0xd7f4, 0xd7f5, 0xd7f6, 0xd7f7,
801 0xd7f8, 0xd7f9, 0xd7fa, 0xd7fb
803 const BYTE
*b
= (const BYTE
*)(ptr
+ 2 * i
);
804 WCHAR wc
= i
< 0x100 ? 0x1100 + i
: hangul_chars
[i
- 0x100];
805 printf( "%04x: %02x %02x %02x %02x %02x\n", wc
, b
[0], b
[1], b
[2], b
[3], b
[4] );
808 printf( "\nExceptions:\n" );
809 for (i
= 0; i
< guid_count
; i
++)
811 if (!guids
[i
].except
) continue;
812 printf( "\n %s\n", get_guid_str( &guids
[i
].id
));
813 dump_exceptions( sortkeys
, guids
[i
].except
);
814 if (!guids
[i
].ling_except
) continue;
815 printf( "\n %s LINGUISTIC_CASING\n", get_guid_str( &guids
[i
].id
));
816 dump_exceptions( sortkeys
, guids
[i
].ling_except
);
822 static const USHORT
*locale_strings
;
823 static DWORD locale_strings_len
;
825 static const char *get_locale_string( DWORD offset
)
827 static char buffer
[1024];
831 if (offset
>= locale_strings_len
) return "<invalid>";
832 len
= locale_strings
[offset
];
833 if (offset
+ len
+ 1 > locale_strings_len
) return "<invalid>";
834 p
= locale_strings
+ offset
+ 1;
840 i
+= sprintf( buffer
+ i
, "\\%03o", *p
);
848 buffer
[i
++] = 0xc0 | (*p
>> 6);
849 buffer
[i
++] = 0x80 | (*p
& 0x3f);
851 else if (*p
>= 0xd800 && *p
<= 0xdbff)
853 int val
= 0x10000 + ((*p
& 0x3ff) << 10) + (p
[1] & 0x3ff);
854 buffer
[i
++] = 0xf0 | (val
>> 18);
855 buffer
[i
++] = 0x80 | ((val
>> 12) & 0x3f);
856 buffer
[i
++] = 0x80 | ((val
>> 6) & 0x3f);
857 buffer
[i
++] = 0x80 | (val
& 0x3f);
863 buffer
[i
++] = 0xe0 | (*p
>> 12);
864 buffer
[i
++] = 0x80 | ((*p
>> 6) & 0x3f);
865 buffer
[i
++] = 0x80 | (*p
& 0x3f);
874 static const char *get_locale_strarray( DWORD offset
)
876 static char buffer
[2048];
880 if (offset
>= locale_strings_len
) return "<invalid>";
881 count
= locale_strings
[offset
];
882 if (offset
+ 1 + count
* 2 > locale_strings_len
) return "<invalid>";
883 array
= (const DWORD
*)(locale_strings
+ offset
+ 1);
887 if (i
> 1) buffer
[i
++] = ' ';
888 i
+= sprintf( buffer
+ i
, "%s", get_locale_string( *array
++ ));
895 static const char *get_locale_uints( DWORD offset
)
897 static char buffer
[1024];
899 const unsigned int *p
;
902 if (offset
>= locale_strings_len
) return "<invalid>";
903 len
= locale_strings
[offset
];
904 if (offset
+ len
+ 1 > locale_strings_len
) return "<invalid>";
905 if (len
< 2) return "[]";
906 for (p
= (unsigned int *)(locale_strings
+ offset
+ 1); len
>= 2; p
++, len
-= 2)
907 sprintf( buffer
+ strlen(buffer
), " %08x", *p
);
909 strcat( buffer
, "]" );
913 static void dump_locale_table( const void *data_ptr
, unsigned int len
)
915 const struct calendar
917 USHORT icalintvalue
; /* 00 */
918 USHORT itwodigityearmax
; /* 02 */
919 UINT sshortdate
; /* 04 */
920 UINT syearmonth
; /* 08 */
921 UINT slongdate
; /* 0c */
922 UINT serastring
; /* 10 */
923 UINT iyearoffsetrange
; /* 14 */
924 UINT sdayname
; /* 18 */
925 UINT sabbrevdayname
; /* 1c */
926 UINT smonthname
; /* 20 */
927 UINT sabbrevmonthname
; /* 24 */
928 UINT scalname
; /* 28 */
929 UINT smonthday
; /* 2c */
930 UINT sabbreverastring
; /* 30 */
931 UINT sshortestdayname
; /* 34 */
932 UINT srelativelongdate
; /* 38 */
933 UINT unused
[3]; /* 3c */
936 const NLS_LOCALE_HEADER
*data
= data_ptr
;
937 const NLS_LOCALE_LCID_INDEX
*id
;
938 const NLS_LOCALE_LCNAME_INDEX
*lcname
;
939 const NLS_LOCALE_DATA
*locale
;
941 int *indices
, nb_aliases
= 0;
943 printf( "offset: %08x\n", data
->offset
);
944 printf( "version: %u\n", data
->version
);
945 printf( "magic: %.4s\n", (char *)&data
->magic
);
947 locale_strings
= (const USHORT
*)((const BYTE
*)data
+ data
->strings_offset
);
948 locale_strings_len
= (const USHORT
*)((const BYTE
*)data
+ len
) - locale_strings
;
950 printf( "\nLCID to locale: (count=%u)\n", data
->nb_lcids
);
951 id
= (const NLS_LOCALE_LCID_INDEX
*)((const BYTE
*)data
+ data
->lcids_offset
);
952 for (i
= 0; i
< data
->nb_lcids
; i
++)
954 printf( " lcid %08x %s\n", id
[i
].id
, get_locale_string( id
[i
].name
));
957 printf( "\nName to locale: (count=%u)\n", data
->nb_lcnames
);
958 indices
= calloc( data
->nb_locales
, sizeof(*indices
) );
959 lcname
= (const NLS_LOCALE_LCNAME_INDEX
*)((const BYTE
*)data
+ data
->lcnames_offset
);
960 for (i
= 0; i
< data
->nb_lcnames
; i
++)
962 printf( " lcid %08x %s\n", lcname
[i
].id
, get_locale_string( lcname
[i
].name
));
963 if (indices
[lcname
[i
].idx
]++) nb_aliases
++;
965 printf( "\nAliases: (count=%u)\n", nb_aliases
);
966 for (i
= 0; i
< data
->nb_lcnames
; i
++)
968 int idx
= lcname
[i
].idx
;
969 if (indices
[idx
] == 1) continue;
970 if (!indices
[idx
]) printf( " unused index %u\n", i
);
974 for (j
= 0; j
< data
->nb_lcnames
; j
++)
975 if (lcname
[j
].idx
== idx
)
976 printf( " %08x %s", lcname
[j
].id
, get_locale_string( lcname
[j
].name
));
982 printf( "\nLocales: (count=%u)\n", data
->nb_locales
);
983 memset( indices
, 0, data
->nb_locales
* sizeof(*indices
) );
984 for (i
= 0; i
< data
->nb_lcnames
; i
++)
986 if (indices
[lcname
[i
].idx
]++) continue;
987 locale
= (const NLS_LOCALE_DATA
*)((const BYTE
*)data
+ data
->locales_offset
+ lcname
[i
].idx
* data
->locale_size
);
988 printf( "Locale %s\n", get_locale_string( locale
->sname
));
989 printf( " LOCALE_SNAME %s\n", get_locale_string( locale
->sname
));
990 printf( " LOCALE_SOPENTYPELANGUAGETAG %s\n", get_locale_string( locale
->sopentypelanguagetag
));
991 printf( " LOCALE_ILANGUAGE %04x\n", locale
->ilanguage
);
992 printf( " unique_lcid %04x\n", locale
->unique_lcid
);
993 printf( " LOCALE_IDIGITS %u\n", locale
->idigits
);
994 printf( " LOCALE_INEGNUMBER %u\n", locale
->inegnumber
);
995 printf( " LOCALE_ICURRDIGITS %u\n", locale
->icurrdigits
);
996 printf( " LOCALE_ICURRENCY %u\n", locale
->icurrency
);
997 printf( " LOCALE_INEGCURR %u\n", locale
->inegcurr
);
998 printf( " LOCALE_ILZERO %u\n", locale
->ilzero
);
999 printf( " LOCALE_INEUTRAL %u\n", !locale
->inotneutral
);
1000 printf( " LOCALE_IFIRSTDAYOFWEEK %u\n", (locale
->ifirstdayofweek
+ 6) % 7 );
1001 printf( " LOCALE_IFIRSTWEEKOFYEAR %u\n", locale
->ifirstweekofyear
);
1002 printf( " LOCALE_ICOUNTRY %u\n", locale
->icountry
);
1003 printf( " LOCALE_IMEASURE %u\n", locale
->imeasure
);
1004 printf( " LOCALE_IDIGITSUBSTITUTION %u\n", locale
->idigitsubstitution
);
1005 printf( " LOCALE_SGROUPING %s\n", get_locale_string( locale
->sgrouping
));
1006 printf( " LOCALE_SMONGROUPING %s\n", get_locale_string( locale
->smongrouping
));
1007 printf( " LOCALE_SLIST %s\n", get_locale_string( locale
->slist
));
1008 printf( " LOCALE_SDECIMAL %s\n", get_locale_string( locale
->sdecimal
));
1009 printf( " LOCALE_STHOUSAND %s\n", get_locale_string( locale
->sthousand
));
1010 printf( " LOCALE_SCURRENCY %s\n", get_locale_string( locale
->scurrency
));
1011 printf( " LOCALE_SMONDECIMALSEP %s\n", get_locale_string( locale
->smondecimalsep
));
1012 printf( " LOCALE_SMONTHOUSANDSEP %s\n", get_locale_string( locale
->smonthousandsep
));
1013 printf( " LOCALE_SPOSITIVESIGN %s\n", get_locale_string( locale
->spositivesign
));
1014 printf( " LOCALE_SNEGATIVESIGN %s\n", get_locale_string( locale
->snegativesign
));
1015 printf( " LOCALE_S1159 %s\n", get_locale_string( locale
->s1159
));
1016 printf( " LOCALE_S2359 %s\n", get_locale_string( locale
->s2359
));
1017 printf( " LOCALE_SNATIVEDIGITS %s\n", get_locale_strarray( locale
->snativedigits
));
1018 printf( " LOCALE_STIMEFORMAT %s\n", get_locale_strarray( locale
->stimeformat
));
1019 printf( " LOCALE_SSHORTDATE %s\n", get_locale_strarray( locale
->sshortdate
));
1020 printf( " LOCALE_SLONGDATE %s\n", get_locale_strarray( locale
->slongdate
));
1021 printf( " LOCALE_SYEARMONTH %s\n", get_locale_strarray( locale
->syearmonth
));
1022 printf( " LOCALE_SDURATION %s\n", get_locale_strarray( locale
->sduration
));
1023 printf( " LOCALE_IDEFAULTLANGUAGE %04x\n", locale
->idefaultlanguage
);
1024 printf( " LOCALE_IDEFAULTANSICODEPAGE %u\n", locale
->idefaultansicodepage
);
1025 printf( " LOCALE_IDEFAULTCODEPAGE %u\n", locale
->idefaultcodepage
);
1026 printf( " LOCALE_IDEFAULTMACCODEPAGE %u\n", locale
->idefaultmaccodepage
);
1027 printf( " LOCALE_IDEFAULTEBCDICCODEPAGE %u\n", locale
->idefaultebcdiccodepage
);
1028 printf( " old_geoid(?) %u\n", locale
->old_geoid
);
1029 printf( " LOCALE_IPAPERSIZE %u\n", locale
->ipapersize
);
1030 printf( " islamic_cal %u %u\n", locale
->islamic_cal
[0], locale
->islamic_cal
[1] );
1031 printf( " LOCALE_SCALENDARTYPE %s\n", get_locale_string( locale
->scalendartype
));
1032 printf( " LOCALE_SABBREVLANGNAME %s\n", get_locale_string( locale
->sabbrevlangname
));
1033 printf( " LOCALE_SISO639LANGNAME %s\n", get_locale_string( locale
->siso639langname
));
1034 printf( " LOCALE_SENGLANGUAGE %s\n", get_locale_string( locale
->senglanguage
));
1035 printf( " LOCALE_SNATIVELANGNAME %s\n", get_locale_string( locale
->snativelangname
));
1036 printf( " LOCALE_SENGCOUNTRY %s\n", get_locale_string( locale
->sengcountry
));
1037 printf( " LOCALE_SNATIVECTRYNAME %s\n", get_locale_string( locale
->snativectryname
));
1038 printf( " LOCALE_SABBREVCTRYNAME %s\n", get_locale_string( locale
->sabbrevctryname
));
1039 printf( " LOCALE_SISO3166CTRYNAME %s\n", get_locale_string( locale
->siso3166ctryname
));
1040 printf( " LOCALE_SINTLSYMBOL %s\n", get_locale_string( locale
->sintlsymbol
));
1041 printf( " LOCALE_SENGCURRNAME %s\n", get_locale_string( locale
->sengcurrname
));
1042 printf( " LOCALE_SNATIVECURRNAME %s\n", get_locale_string( locale
->snativecurrname
));
1043 printf( " LOCALE_FONTSIGNATURE %s\n", get_locale_uints( locale
->fontsignature
));
1044 printf( " LOCALE_SISO639LANGNAME2 %s\n", get_locale_string( locale
->siso639langname2
));
1045 printf( " LOCALE_SISO3166CTRYNAME2 %s\n", get_locale_string( locale
->siso3166ctryname2
));
1046 printf( " LOCALE_SPARENT %s\n", get_locale_string( locale
->sparent
));
1047 printf( " LOCALE_SDAYNAME %s\n", get_locale_strarray( locale
->sdayname
));
1048 printf( " LOCALE_SABBREVDAYNAME %s\n", get_locale_strarray( locale
->sabbrevdayname
));
1049 printf( " LOCALE_SMONTHNAME %s\n", get_locale_strarray( locale
->smonthname
));
1050 printf( " LOCALE_SABBREVMONTHNAME %s\n", get_locale_strarray( locale
->sabbrevmonthname
));
1051 printf( " LOCALE_SGENITIVEMONTH %s\n", get_locale_strarray( locale
->sgenitivemonth
));
1052 printf( " LOCALE_SABBREVGENITIVEMONTH %s\n", get_locale_strarray( locale
->sabbrevgenitivemonth
));
1053 printf( " calendar names %s\n", get_locale_strarray( locale
->calnames
));
1054 printf( " sort names %s\n", get_locale_strarray( locale
->customsorts
));
1055 printf( " LOCALE_INEGATIVEPERCENT %u\n", locale
->inegativepercent
);
1056 printf( " LOCALE_IPOSITIVEPERCENT %u\n", locale
->ipositivepercent
);
1057 printf( " unknown1 %04x\n", locale
->unknown1
);
1058 printf( " LOCALE_IREADINGLAYOUT %u\n", locale
->ireadinglayout
);
1059 printf( " unknown2 %04x %04x\n", locale
->unknown2
[0], locale
->unknown2
[1] );
1060 printf( " unused1 %04x\n", locale
->unused1
);
1061 printf( " LOCALE_SENGLISHDISPLAYNAME %s\n", get_locale_string( locale
->sengdisplayname
));
1062 printf( " LOCALE_SNATIVEDISPLAYNAME %s\n", get_locale_string( locale
->snativedisplayname
));
1063 printf( " LOCALE_SPERCENT %s\n", get_locale_string( locale
->spercent
));
1064 printf( " LOCALE_SNAN %s\n", get_locale_string( locale
->snan
));
1065 printf( " LOCALE_SPOSINFINITY %s\n", get_locale_string( locale
->sposinfinity
));
1066 printf( " LOCALE_SNEGINFINITY %s\n", get_locale_string( locale
->sneginfinity
));
1067 printf( " unused2 %04x\n", locale
->unused2
);
1068 printf( " CAL_SERASTRING %s\n", get_locale_string( locale
->serastring
));
1069 printf( " CAL_SABBREVERASTRING %s\n", get_locale_string( locale
->sabbreverastring
));
1070 printf( " unused3 %04x\n", locale
->unused3
);
1071 printf( " LOCALE_SCONSOLEFALLBACKNAME %s\n", get_locale_string( locale
->sconsolefallbackname
));
1072 printf( " LOCALE_SSHORTTIME %s\n", get_locale_strarray( locale
->sshorttime
));
1073 printf( " LOCALE_SSHORTESTDAYNAME %s\n", get_locale_strarray( locale
->sshortestdayname
));
1074 printf( " unused4 %04x\n", locale
->unused4
);
1075 printf( " LOCALE_SSORTLOCALE %s\n", get_locale_string( locale
->ssortlocale
));
1076 printf( " LOCALE_SKEYBOARDSTOINSTALL %s\n", get_locale_string( locale
->skeyboardstoinstall
));
1077 printf( " LOCALE_SSCRIPTS %s\n", get_locale_string( locale
->sscripts
));
1078 printf( " LOCALE_SRELATIVELONGDATE %s\n", get_locale_string( locale
->srelativelongdate
));
1079 printf( " LOCALE_IGEOID %u\n", locale
->igeoid
);
1080 printf( " LOCALE_SSHORTESTAM %s\n", get_locale_string( locale
->sshortestam
));
1081 printf( " LOCALE_SSHORTESTPM %s\n", get_locale_string( locale
->sshortestpm
));
1082 printf( " LOCALE_SMONTHDAY %s\n", get_locale_strarray( locale
->smonthday
));
1083 printf( " keyboard layout %s\n", get_locale_string( locale
->keyboard_layout
));
1086 printf( "\nCalendars: (count=%u)\n\n", data
->nb_calendars
);
1087 for (i
= 0; i
< data
->nb_calendars
; i
++)
1089 calendar
= (const struct calendar
*)((const BYTE
*)data
+ data
->calendars_offset
+ i
* data
->calendar_size
);
1090 printf( "calendar %u:\n", i
+ 1 );
1091 printf( " CAL_ICALINTVALUE %u\n", calendar
->icalintvalue
);
1092 printf( " CAL_ITWODIGITYEARMAX %u\n", calendar
->itwodigityearmax
);
1093 printf( " CAL_SSHORTDATE %s\n", get_locale_strarray( calendar
->sshortdate
));
1094 printf( " CAL_SYEARMONTH %s\n", get_locale_strarray( calendar
->syearmonth
));
1095 printf( " CAL_SLONGDATE %s\n", get_locale_strarray( calendar
->slongdate
));
1096 printf( " CAL_SERASTRING %s\n", get_locale_strarray( calendar
->serastring
));
1097 printf( " CAL_IYEAROFFSETRANGE {" );
1098 if (calendar
->iyearoffsetrange
)
1100 UINT count
= locale_strings
[calendar
->iyearoffsetrange
];
1101 const DWORD
*array
= (const DWORD
*)(locale_strings
+ calendar
->iyearoffsetrange
+ 1);
1104 const short *p
= (const short *)locale_strings
+ *array
++;
1105 printf( " era=%d,from=%d.%d.%d,zero=%d,first=%d", p
[1], p
[2], p
[3], p
[4], p
[5], p
[6] );
1109 printf( " CAL_SDAYNAME %s\n", get_locale_strarray( calendar
->sdayname
));
1110 printf( " CAL_SABBREVDAYNAME %s\n", get_locale_strarray( calendar
->sabbrevdayname
));
1111 printf( " CAL_SMONTHNAME %s\n", get_locale_strarray( calendar
->smonthname
));
1112 printf( " CAL_SABBREVMONTHNAME %s\n", get_locale_strarray( calendar
->sabbrevmonthname
));
1113 printf( " CAL_SCALNAME %s\n", get_locale_string( calendar
->scalname
));
1114 printf( " CAL_SMONTHDAY %s\n", get_locale_strarray( calendar
->smonthday
));
1115 printf( " CAL_SABBREVERASTRING %s\n", get_locale_strarray( calendar
->sabbreverastring
));
1116 printf( " CAL_SSHORTESTDAYNAME %s\n", get_locale_strarray( calendar
->sshortestdayname
));
1117 printf( " CAL_SRELATIVELONGDATE %s\n", get_locale_string( calendar
->srelativelongdate
));
1118 printf( " unused %04x %04x %04x\n",
1119 calendar
->unused
[0], calendar
->unused
[1], calendar
->unused
[2] );
1124 static void dump_char_maps( const USHORT
*ptr
)
1128 printf( "\nMAP_FOLDDIGITS:\n\n" );
1130 dump_offset_table( ptr
, len
);
1133 printf( "\n\nCompatibility map:\n" );
1135 dump_offset_table( ptr
, len
);
1138 printf( "\n\nLCMAP_HIRAGANA:\n" );
1140 dump_offset_table( ptr
, len
);
1143 printf( "\n\nLCMAP_KATAKANA:\n" );
1145 dump_offset_table( ptr
, len
);
1148 printf( "\n\nLCMAP_HALFWIDTH:\n" );
1150 dump_offset_table( ptr
, len
);
1153 printf( "\n\nLCMAP_FULLWIDTH:\n" );
1155 dump_offset_table( ptr
, len
);
1158 printf( "\n\nLCMAP_TRADITIONAL_CHINESE:\n" );
1160 dump_offset_table( ptr
, len
);
1163 printf( "\n\nLCMAP_SIMPLIFIED_CHINESE:\n" );
1165 dump_offset_table( ptr
, len
);
1168 printf( "\n\nUnknown table 1\n" );
1170 dump_offset_table( ptr
, len
);
1173 printf( "\n\nUnknown table 2:\n" );
1176 dump_offset_table( ptr
, len
);
1178 dump_offset_table( ptr
, len
);
1182 static void dump_scripts( const DWORD
*ptr
)
1190 int i
, j
, nb_ranges
, nb_names
;
1195 range
= (const struct range
*)ptr
;
1196 names
= (const WCHAR
*)(range
+ nb_ranges
);
1197 for (i
= 0; i
< nb_ranges
; i
++)
1199 printf( "%08x-%08x", range
[i
].from
, range
[i
].to
);
1200 for (j
= 0; j
< min( nb_names
, 16 * 8 ); j
++)
1201 if ((range
[i
].mask
[j
/ 8] & (1 << (j
% 8))))
1202 printf( " %s", get_unicode_str( names
+ j
* 4, 4 ));
1208 static void dump_locale(void)
1225 if (!(header
= PRD( 0, sizeof(*header
) ))) return;
1226 nb_tables
= header
->ctypes
/ 4;
1227 for (i
= 8; i
< nb_tables
; i
++)
1228 printf( "Table%u: %08x\n", i
, header
->tables
[i
- 8] );
1230 if (!(ptr
= PRD( header
->ctypes
, header
->locales
- header
->ctypes
))) return;
1231 printf( "\nCTYPE table:\n\n" );
1232 dump_ctype_table( ptr
);
1234 if (!(ptr
= PRD( header
->locales
, header
->charmaps
- header
->locales
))) return;
1235 printf( "\nLocales:\n" );
1236 dump_locale_table( ptr
, header
->charmaps
- header
->locales
);
1238 if (!(ptr
= PRD( header
->charmaps
, header
->geoids
- header
->charmaps
))) return;
1239 printf( "\nCharacter mapping tables:\n\n" );
1240 dump_char_maps( ptr
);
1242 if (!(ptr
= PRD( header
->geoids
, header
->scripts
- header
->geoids
))) return;
1243 printf( "\nGeographic regions:\n\n" );
1244 dump_geo_table( ptr
);
1246 if (!(ptr
= PRD( header
->scripts
, dump_total_len
- header
->scripts
))) return;
1247 printf( "\nScripts:\n\n" );
1248 dump_scripts( ptr
);
1251 static void dump_ctype(void)
1255 if (!(ptr
= PRD( 0, dump_total_len
))) return;
1256 dump_ctype_table( ptr
);
1259 static void dump_geo(void)
1263 if (!(ptr
= PRD( 0, dump_total_len
))) return;
1264 dump_geo_table( ptr
);
1269 const char *name
= get_basename( globals
.input_name
);
1270 if (!strcasecmp( name
, "l_intl.nls" )) return dump_casemap();
1271 if (!strncasecmp( name
, "c_", 2 )) return dump_codepage();
1272 if (!strncasecmp( name
, "norm", 4 )) return dump_norm();
1273 if (!strcasecmp( name
, "ctype.nls" )) return dump_ctype();
1274 if (!strcasecmp( name
, "geo.nls" )) return dump_geo();
1275 if (!strcasecmp( name
, "locale.nls" )) return dump_locale();
1276 if (!strcasecmp( name
, "sortdefault.nls" )) return dump_sort( 0 );
1277 if (!strncasecmp( name
, "sort", 4 )) return dump_sort( 1 );
1278 fprintf( stderr
, "Unrecognized file name '%s'\n", globals
.input_name
);
1281 enum FileSig
get_kind_nls(void)
1283 if (strlen( globals
.input_name
) < 5) return SIG_UNKNOWN
;
1284 if (strcasecmp( globals
.input_name
+ strlen(globals
.input_name
) - 4, ".nls" )) return SIG_UNKNOWN
;