4 * Copyright 1998,2000 Bertho A. Stultiens
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
35 #define SUPPRESS_YACC_ERROR_MESSAGE
37 static void generic_msg(const char *s
, const char *t
, va_list ap
)
39 fprintf(stderr
, "%s:%d:%d: %s: ", input_name
? input_name
: "stdin", line_number
, char_number
, t
);
40 vfprintf(stderr
, s
, ap
);
44 * The yyerror routine should not exit because we use the error-token
45 * to determine the syntactic error in the source. However, YACC
46 * uses the same routine to print an error just before the error
48 * The extra routine 'xyyerror' is used to exit after giving a real
51 int mcy_error(const char *s
, ...)
53 #ifndef SUPPRESS_YACC_ERROR_MESSAGE
56 generic_msg(s
, "Yacc error", ap
);
62 int xyyerror(const char *s
, ...)
66 generic_msg(s
, "Error", ap
);
72 int mcy_warning(const char *s
, ...)
76 generic_msg(s
, "Warning", ap
);
81 void internal_error(const char *file
, int line
, const char *s
, ...)
85 fprintf(stderr
, "Internal error (please report) %s %d: ", file
, line
);
86 vfprintf(stderr
, s
, ap
);
91 void fatal_perror( const char *msg
, ... )
94 va_start( valist
, msg
);
95 fprintf(stderr
, "Error: ");
96 vfprintf( stderr
, msg
, valist
);
102 void error(const char *s
, ...)
106 fprintf(stderr
, "Error: ");
107 vfprintf(stderr
, s
, ap
);
112 void warning(const char *s
, ...)
116 fprintf(stderr
, "Warning: ");
117 vfprintf(stderr
, s
, ap
);
121 int unistrlen(const WCHAR
*s
)
124 for(n
= 0; *s
; n
++, s
++)
129 WCHAR
*unistrcpy(WCHAR
*dst
, const WCHAR
*src
)
138 WCHAR
*xunistrdup(const WCHAR
* str
)
143 s
= xmalloc((unistrlen(str
)+1) * sizeof(WCHAR
));
144 return unistrcpy(s
, str
);
147 int unistricmp(const WCHAR
*s1
, const WCHAR
*s2
)
151 static const char warn
[] = "Don't know the uppercase equivalent of non ascii characters;"
152 "comparison might yield wrong results";
155 if((*s1
& 0xffff) > 0x7f || (*s2
& 0xffff) > 0x7f)
165 i
= toupper(*s1
++) - toupper(*s2
++);
170 if((*s1
& 0xffff) > 0x7f || (*s2
& 0xffff) > 0x7f)
177 return toupper(*s1
) - toupper(*s2
);
180 int unistrcmp(const WCHAR
*s1
, const WCHAR
*s2
)
193 WCHAR
*utf8_to_unicode( const char *src
, int srclen
, int *dstlen
)
195 static const char utf8_length
[128] =
197 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
198 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
199 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
200 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
201 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
202 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
203 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
204 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
206 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
208 const char *srcend
= src
+ srclen
;
212 dst
= ret
= xmalloc( (srclen
+ 1) * sizeof(WCHAR
) );
215 unsigned char ch
= *src
++;
216 if (ch
< 0x80) /* special fast case for 7-bit ASCII */
221 len
= utf8_length
[ch
- 0x80];
222 if (len
&& src
+ len
<= srcend
)
224 res
= ch
& utf8_mask
[len
];
228 if ((ch
= *src
^ 0x80) >= 0x40) break;
229 res
= (res
<< 6) | ch
;
231 if (res
< 0x10) break;
233 if ((ch
= *src
^ 0x80) >= 0x40) break;
234 res
= (res
<< 6) | ch
;
235 if (res
>= 0x110000 >> 6) break;
237 if (res
< 0x20) break;
238 if (res
>= 0xd800 >> 6 && res
<= 0xdfff >> 6) break;
240 if ((ch
= *src
^ 0x80) >= 0x40) break;
241 res
= (res
<< 6) | ch
;
243 if (res
< 0x80) break;
244 if (res
<= 0xffff) *dst
++ = res
;
248 *dst
++ = 0xd800 | (res
>> 10);
249 *dst
++ = 0xdc00 | (res
& 0x3ff);
261 char *unicode_to_utf8( const WCHAR
*src
, int srclen
, int *dstlen
)
265 dst
= ret
= xmalloc( srclen
* 3 + 1 );
266 for ( ; srclen
; srclen
--, src
++)
268 unsigned int ch
= *src
;
270 if (ch
< 0x80) /* 0x00-0x7f: 1 byte */
275 if (ch
< 0x800) /* 0x80-0x7ff: 2 bytes */
277 dst
[1] = 0x80 | (ch
& 0x3f);
283 if (ch
>= 0xd800 && ch
<= 0xdbff && srclen
> 1 && src
[1] >= 0xdc00 && src
[1] <= 0xdfff)
285 /* 0x10000-0x10ffff: 4 bytes */
286 ch
= 0x10000 + ((ch
& 0x3ff) << 10) + (src
[1] & 0x3ff);
287 dst
[3] = 0x80 | (ch
& 0x3f);
289 dst
[2] = 0x80 | (ch
& 0x3f);
291 dst
[1] = 0x80 | (ch
& 0x3f);
299 if (ch
>= 0xd800 && ch
<= 0xdfff) ch
= 0xfffd; /* invalid surrogate pair */
301 /* 0x800-0xffff: 3 bytes */
302 dst
[2] = 0x80 | (ch
& 0x3f);
304 dst
[1] = 0x80 | (ch
& 0x3f);
316 int is_valid_codepage(int id
)
318 return IsValidCodePage( id
);
321 WCHAR
*codepage_to_unicode( int codepage
, const char *src
, int srclen
, int *dstlen
)
323 WCHAR
*dst
= xmalloc( (srclen
+ 1) * sizeof(WCHAR
) );
324 DWORD ret
= MultiByteToWideChar( codepage
, MB_ERR_INVALID_CHARS
, src
, srclen
, dst
, srclen
);
325 if (!ret
) return NULL
;
331 unsigned int get_language_from_name( const char *name
)
333 WCHAR nameW
[LOCALE_NAME_MAX_LENGTH
];
335 MultiByteToWideChar( 1252, 0, name
, -1, nameW
, ARRAY_SIZE(nameW
) );
336 return LocaleNameToLCID( nameW
, LOCALE_ALLOW_NEUTRAL_NAMES
);
343 unsigned short codepage
;
344 unsigned short unidef
;
345 unsigned short trans_unidef
;
346 unsigned short *cp2uni
;
347 unsigned short *dbcs_offsets
;
350 static struct nls_info nlsinfo
[128];
352 static void init_nls_info( struct nls_info
*info
, unsigned short *ptr
)
354 unsigned short hdr_size
= ptr
[0];
356 info
->codepage
= ptr
[1];
357 info
->unidef
= ptr
[4];
358 info
->trans_unidef
= ptr
[6];
360 info
->cp2uni
= ++ptr
;
362 if (*ptr
++) ptr
+= 256; /* glyph table */
363 info
->dbcs_offsets
= *ptr
? ptr
+ 1 : NULL
;
366 static void *load_nls_file( const char *name
)
372 for (i
= 0; nlsdirs
[i
]; i
++)
374 char *path
= strmake( "%s/%s", nlsdirs
[i
], name
);
375 if ((data
= read_file( path
, &size
)))
385 static const struct nls_info
*get_nls_info( unsigned int codepage
)
387 unsigned short *data
;
390 for (i
= 0; i
< ARRAY_SIZE(nlsinfo
) && nlsinfo
[i
].codepage
; i
++)
391 if (nlsinfo
[i
].codepage
== codepage
) return &nlsinfo
[i
];
393 assert( i
< ARRAY_SIZE(nlsinfo
) );
395 if ((data
= load_nls_file( strmake( "c_%03u.nls", codepage
))))
397 init_nls_info( &nlsinfo
[i
], data
);
403 int is_valid_codepage(int cp
)
405 return cp
== CP_UTF8
|| get_nls_info( cp
);
408 WCHAR
*codepage_to_unicode( int codepage
, const char *src
, int srclen
, int *dstlen
)
410 const struct nls_info
*info
= get_nls_info( codepage
);
412 WCHAR dbch
, *dst
= xmalloc( (srclen
+ 1) * sizeof(WCHAR
) );
414 if (!info
) error( "codepage %u not supported\n", codepage
);
416 if (info
->dbcs_offsets
)
418 for (i
= 0; srclen
; i
++, srclen
--, src
++)
420 unsigned short off
= info
->dbcs_offsets
[(unsigned char)*src
];
423 if (srclen
== 1) return NULL
;
424 dbch
= (src
[0] << 8) | (unsigned char)src
[1];
427 dst
[i
] = info
->dbcs_offsets
[off
+ (unsigned char)*src
];
428 if (dst
[i
] == info
->unidef
&& dbch
!= info
->trans_unidef
) return NULL
;
432 dst
[i
] = info
->cp2uni
[(unsigned char)*src
];
433 if (dst
[i
] == info
->unidef
&& *src
!= info
->trans_unidef
) return NULL
;
439 for (i
= 0; i
< srclen
; i
++)
441 dst
[i
] = info
->cp2uni
[(unsigned char)src
[i
]];
442 if (dst
[i
] == info
->unidef
&& src
[i
] != info
->trans_unidef
) return NULL
;
450 static const NLS_LOCALE_LCID_INDEX
*lcids_index
;
451 static const NLS_LOCALE_HEADER
*locale_table
;
452 static const NLS_LOCALE_LCNAME_INDEX
*lcnames_index
;
453 static const WCHAR
*locale_strings
;
455 static void load_locale_nls(void)
460 unsigned int unknown1
;
461 unsigned int unknown2
;
462 unsigned int unknown3
;
463 unsigned int locales
;
464 unsigned int charmaps
;
466 unsigned int scripts
;
469 if (!(header
= load_nls_file( "locale.nls" ))) error( "unable to load locale.nls\n" );
470 locale_table
= (const NLS_LOCALE_HEADER
*)((char *)header
+ header
->locales
);
471 lcids_index
= (const NLS_LOCALE_LCID_INDEX
*)((char *)locale_table
+ locale_table
->lcids_offset
);
472 lcnames_index
= (const NLS_LOCALE_LCNAME_INDEX
*)((char *)locale_table
+ locale_table
->lcnames_offset
);
473 locale_strings
= (const WCHAR
*)((char *)locale_table
+ locale_table
->strings_offset
);
476 static int compare_locale_names( const char *n1
, const WCHAR
*n2
)
480 WCHAR ch1
= (unsigned char)*n1
++;
482 if (ch1
>= 'a' && ch1
<= 'z') ch1
-= 'a' - 'A';
483 if (ch2
>= 'a' && ch2
<= 'z') ch2
-= 'a' - 'A';
484 if (!ch1
|| ch1
!= ch2
) return ch1
- ch2
;
488 static const NLS_LOCALE_LCNAME_INDEX
*find_lcname_entry( const char *name
)
490 int min
= 0, max
= locale_table
->nb_lcnames
- 1;
492 if (!name
) return NULL
;
495 int res
, pos
= (min
+ max
) / 2;
496 const WCHAR
*str
= locale_strings
+ lcnames_index
[pos
].name
;
497 res
= compare_locale_names( name
, str
+ 1 );
498 if (res
< 0) max
= pos
- 1;
499 else if (res
> 0) min
= pos
+ 1;
500 else return &lcnames_index
[pos
];
505 static const NLS_LOCALE_DATA
*get_locale_data( UINT idx
)
507 ULONG offset
= locale_table
->locales_offset
+ idx
* locale_table
->locale_size
;
508 return (const NLS_LOCALE_DATA
*)((const char *)locale_table
+ offset
);
511 unsigned int get_language_from_name( const char *name
)
513 const NLS_LOCALE_LCNAME_INDEX
*entry
;
515 if (!locale_table
) load_locale_nls();
516 if (!(entry
= find_lcname_entry( name
))) return 0;
517 return get_locale_data( entry
->idx
)->unique_lcid
;
522 unsigned char *output_buffer
;
523 size_t output_buffer_pos
;
524 size_t output_buffer_size
;