39 #include "kmp_debug.h"
50 #include "kmp_i18n_default.inc"
52 #include "kmp_environment.h"
56 #define get_section( id ) ( (id) >> 16 )
57 #define get_number( id ) ( (id) & 0xFFFF )
59 kmp_msg_t __kmp_msg_empty = { kmp_mt_dummy, 0,
"", 0 };
60 kmp_msg_t __kmp_msg_null = { kmp_mt_dummy, 0, NULL, 0 };
61 static char const * no_message_available =
"(No message available)";
63 enum kmp_i18n_cat_status {
68 typedef enum kmp_i18n_cat_status kmp_i18n_cat_status_t;
69 static volatile kmp_i18n_cat_status_t status = KMP_I18N_CLOSED;
79 static void __kmp_i18n_do_catopen();
80 static kmp_bootstrap_lock_t lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( lock );
88 if ( status == KMP_I18N_CLOSED ) {
89 __kmp_acquire_bootstrap_lock( & lock );
90 if ( status == KMP_I18N_CLOSED ) {
91 __kmp_i18n_do_catopen();
93 __kmp_release_bootstrap_lock( & lock );
107 #include <nl_types.h>
109 #define KMP_I18N_NULLCAT ((nl_catd)( -1 ))
110 static nl_catd cat = KMP_I18N_NULLCAT;
111 static char const * name = ( KMP_VERSION_MAJOR == 4 ?
"libguide.cat" :
"libiomp5.cat" );
121 __kmp_i18n_do_catopen(
124 char * lang = __kmp_env_get(
"LANG" );
127 KMP_DEBUG_ASSERT( status == KMP_I18N_CLOSED );
128 KMP_DEBUG_ASSERT( cat == KMP_I18N_NULLCAT );
132 strcmp( lang,
"" ) == 0 ||
133 strcmp( lang,
" " ) == 0 ||
136 strcmp( lang,
"C" ) == 0 ||
137 strcmp( lang,
"POSIX" ) == 0;
143 __kmp_str_split( lang,
'@', & lang, & tail );
144 __kmp_str_split( lang,
'.', & lang, & tail );
145 __kmp_str_split( lang,
'_', & lang, & tail );
146 english = ( strcmp( lang,
"en" ) == 0 );
149 KMP_INTERNAL_FREE( lang );
154 status = KMP_I18N_ABSENT;
158 cat = catopen( name, 0 );
160 status = ( cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED );
162 if ( status == KMP_I18N_ABSENT ) {
163 if (__kmp_generate_warnings > kmp_warnings_low) {
165 char * nlspath = __kmp_env_get(
"NLSPATH" );
166 char * lang = __kmp_env_get(
"LANG" );
172 KMP_MSG( CantOpenMessageCatalog, name ),
174 KMP_HNT( CheckEnvVar,
"NLSPATH", nlspath ),
175 KMP_HNT( CheckEnvVar,
"LANG", lang ),
178 KMP_INFORM( WillUseDefaultMessages );
179 KMP_INTERNAL_FREE( nlspath );
180 KMP_INTERNAL_FREE( lang );
184 int section = get_section( kmp_i18n_prp_Version );
185 int number = get_number( kmp_i18n_prp_Version );
186 char const * expected = __kmp_i18n_default_table.sect[ section ].str[ number ];
188 kmp_str_buf_t version;
189 __kmp_str_buf_init( & version );
190 __kmp_str_buf_print( & version,
"%s", catgets( cat, section, number, NULL ) );
193 if ( strcmp( version.str, expected ) != 0 ) {
194 __kmp_i18n_catclose();
195 status = KMP_I18N_ABSENT;
196 if (__kmp_generate_warnings > kmp_warnings_low) {
198 char const * name =
"NLSPATH";
199 char const * nlspath = __kmp_env_get( name );
202 KMP_MSG( WrongMessageCatalog, name, version.str, expected ),
203 KMP_HNT( CheckEnvVar, name, nlspath ),
206 KMP_INFORM( WillUseDefaultMessages );
207 KMP_INTERNAL_FREE( (
void *) nlspath );
210 __kmp_str_buf_free( & version );
220 if ( status == KMP_I18N_OPENED ) {
221 KMP_DEBUG_ASSERT( cat != KMP_I18N_NULLCAT );
223 cat = KMP_I18N_NULLCAT;
225 status = KMP_I18N_CLOSED;
234 int section = get_section(
id );
235 int number = get_number(
id );
236 char const * message = NULL;
238 if ( 1 <= section && section <= __kmp_i18n_default_table.size ) {
239 if ( 1 <= number && number <= __kmp_i18n_default_table.sect[ section ].size ) {
240 if ( status == KMP_I18N_CLOSED ) {
241 __kmp_i18n_catopen();
243 if ( status == KMP_I18N_OPENED ) {
248 __kmp_i18n_default_table.sect[ section ].str[ number ]
251 if ( message == NULL ) {
252 message = __kmp_i18n_default_table.sect[ section ].str[ number ];
256 if ( message == NULL ) {
257 message = no_message_available;
264 #endif // KMP_OS_UNIX
275 #include "kmp_environment.h"
278 #define KMP_I18N_NULLCAT NULL
279 static HMODULE cat = KMP_I18N_NULLCAT;
280 static char const * name = ( KMP_VERSION_MAJOR == 4 ?
"libguide40ui.dll" :
"libiomp5ui.dll" );
282 static kmp_i18n_table_t table = { 0, NULL };
286 static UINT
const default_code_page = CP_OEMCP;
287 static UINT code_page = default_code_page;
289 static char const * ___catgets( kmp_i18n_id_t
id );
290 static UINT get_code_page();
291 static void kmp_i18n_table_free( kmp_i18n_table_t * table );
298 UINT cp = default_code_page;
299 char const * value = __kmp_env_get(
"KMP_CODEPAGE" );
300 if ( value != NULL ) {
301 if ( _stricmp( value,
"ANSI" ) == 0 ) {
303 }
else if ( _stricmp( value,
"OEM" ) == 0 ) {
305 }
else if ( _stricmp( value,
"UTF-8" ) == 0 || _stricmp( value,
"UTF8" ) == 0 ) {
307 }
else if ( _stricmp( value,
"UTF-7" ) == 0 || _stricmp( value,
"UTF7" ) == 0 ) {
313 KMP_INTERNAL_FREE( (
void *) value );
321 kmp_i18n_table_t * table
325 for ( s = 0; s < table->size; ++ s ) {
326 for ( m = 0; m < table->sect[ s ].size; ++ m ) {
328 KMP_INTERNAL_FREE( (
void *) table->sect[ s ].str[ m ] );
329 table->sect[ s ].str[ m ] = NULL;
331 table->sect[ s ].size = 0;
333 KMP_INTERNAL_FREE ( (
void *) table->sect[ s ].str );
334 table->sect[ s ].str = NULL;
337 KMP_INTERNAL_FREE( (
void *) table->sect );
343 __kmp_i18n_do_catopen(
346 LCID locale_id = GetThreadLocale();
347 WORD lang_id = LANGIDFROMLCID( locale_id );
348 WORD primary_lang_id = PRIMARYLANGID( lang_id );
351 KMP_DEBUG_ASSERT( status == KMP_I18N_CLOSED );
352 KMP_DEBUG_ASSERT( cat == KMP_I18N_NULLCAT );
354 __kmp_str_buf_init( & path );
358 if ( primary_lang_id == LANG_ENGLISH ) {
359 status = KMP_I18N_ABSENT;
377 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
378 reinterpret_cast< LPCSTR >( & __kmp_i18n_do_catopen ),
382 status = KMP_I18N_ABSENT;
390 DWORD drc = GetModuleFileName( handle, path.str, path.size );
392 status = KMP_I18N_ABSENT;
395 if ( drc < path.size ) {
399 __kmp_str_buf_reserve( & path, path.size * 2 );
404 __kmp_str_fname_init( & fname, path.str );
405 __kmp_str_buf_clear( & path );
406 __kmp_str_buf_print( & path,
"%s%lu/%s", fname.dir, (
unsigned long)( locale_id ), name );
407 __kmp_str_fname_free( & fname );
412 cat = LoadLibraryEx( path.str, NULL, LOAD_LIBRARY_AS_DATAFILE );
413 status = ( cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED );
415 if ( status == KMP_I18N_ABSENT ) {
416 if (__kmp_generate_warnings > kmp_warnings_low) {
417 DWORD error = GetLastError();
435 KMP_MSG( CantOpenMessageCatalog, path.str ),
436 KMP_SYSERRCODE( error ),
437 ( error == ERROR_BAD_EXE_FORMAT ? KMP_HNT( BadExeFormat, path.str, KMP_ARCH_STR ) : __kmp_msg_null ),
440 KMP_INFORM( WillUseDefaultMessages );
444 int section = get_section( kmp_i18n_prp_Version );
445 int number = get_number( kmp_i18n_prp_Version );
446 char const * expected = __kmp_i18n_default_table.sect[ section ].str[ number ];
447 kmp_str_buf_t version;
448 __kmp_str_buf_init( & version );
449 __kmp_str_buf_print( & version,
"%s", ___catgets( kmp_i18n_prp_Version ) );
451 if ( strcmp( version.str, expected ) != 0 ) {
453 __kmp_i18n_catclose();
454 status = KMP_I18N_ABSENT;
455 if (__kmp_generate_warnings > kmp_warnings_low) {
459 KMP_MSG( WrongMessageCatalog, path.str, version.str, expected ),
462 KMP_INFORM( WillUseDefaultMessages );
465 __kmp_str_buf_free( & version );
468 code_page = get_code_page();
471 __kmp_str_buf_free( & path );
480 if ( status == KMP_I18N_OPENED ) {
481 KMP_DEBUG_ASSERT( cat != KMP_I18N_NULLCAT );
482 kmp_i18n_table_free( & table );
484 cat = KMP_I18N_NULLCAT;
486 code_page = default_code_page;
487 status = KMP_I18N_CLOSED;
523 if ( str[ in ] !=
'\r' ) {
524 str[ out ] = str[ in ];
527 if ( str[ in ] == 0 ) {
542 char * result = NULL;
544 wchar_t * wmsg = NULL;
550 KMP_DEBUG_ASSERT( cat != KMP_I18N_NULLCAT );
553 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE |
554 FORMAT_MESSAGE_IGNORE_INSERTS,
565 wmsg = (
wchar_t *) addr;
581 msg = (
char *) KMP_INTERNAL_MALLOC( len + 1 );
592 if ( rc <= 0 || rc > len ) {
595 KMP_DEBUG_ASSERT( rc == len );
600 len = ___strip_crs( msg );
603 if ( len >= 1 && msg[ len - 1 ] ==
'\n' ) {
615 KMP_INTERNAL_FREE( msg );
617 if ( wmsg != NULL ) {
631 int section = get_section(
id );
632 int number = get_number(
id );
633 char const * message = NULL;
635 if ( 1 <= section && section <= __kmp_i18n_default_table.size ) {
636 if ( 1 <= number && number <= __kmp_i18n_default_table.sect[ section ].size ) {
637 if ( status == KMP_I18N_CLOSED ) {
638 __kmp_i18n_catopen();
640 if ( cat != KMP_I18N_NULLCAT ) {
641 if ( table.size == 0 ) {
642 table.sect = (kmp_i18n_section_t *)
644 ( __kmp_i18n_default_table.size + 2 ),
645 sizeof( kmp_i18n_section_t )
647 table.size = __kmp_i18n_default_table.size;
649 if ( table.sect[ section ].size == 0 ) {
650 table.sect[ section ].str = (
const char **)
652 __kmp_i18n_default_table.sect[ section ].size + 2,
653 sizeof(
char const * )
655 table.sect[ section ].size = __kmp_i18n_default_table.sect[ section ].size;
657 if ( table.sect[ section ].str[ number ] == NULL ) {
658 table.sect[ section ].str[ number ] = ___catgets(
id );
660 message = table.sect[ section ].str[ number ];
662 if ( message == NULL ) {
664 message = __kmp_i18n_default_table.sect[ section ].str[ number ];
668 if ( message == NULL ) {
669 message = no_message_available;
676 #endif // KMP_OS_WINDOWS
681 #error I18n support is not implemented for this OS.
682 #endif // KMP_I18N_OK
687 __kmp_i18n_dump_catalog(
688 kmp_str_buf_t * buffer
691 struct kmp_i18n_id_range_t {
696 static struct kmp_i18n_id_range_t ranges[] = {
697 { kmp_i18n_prp_first, kmp_i18n_prp_last },
698 { kmp_i18n_str_first, kmp_i18n_str_last },
699 { kmp_i18n_fmt_first, kmp_i18n_fmt_last },
700 { kmp_i18n_msg_first, kmp_i18n_msg_last },
701 { kmp_i18n_hnt_first, kmp_i18n_hnt_last }
704 int num_of_ranges =
sizeof( ranges ) /
sizeof(
struct kmp_i18n_id_range_t );
708 for ( range = 0; range < num_of_ranges; ++ range ) {
709 __kmp_str_buf_print( buffer,
"*** Set #%d ***\n", range + 1 );
710 for (
id = (kmp_i18n_id_t)( ranges[ range ].first + 1 );
711 id < ranges[ range ].last;
712 id = (kmp_i18n_id_t)(
id + 1 ) ) {
713 __kmp_str_buf_print( buffer,
"%d: <<%s>>\n",
id, __kmp_i18n_catgets(
id ) );
717 __kmp_printf(
"%s", buffer->str );
731 kmp_str_buf_t buffer;
732 __kmp_str_buf_init( & buffer );
734 va_start( args,
id );
738 __kmp_str_buf_vprint( & buffer, __kmp_i18n_catgets(
id ), args );
747 FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
748 __kmp_i18n_catgets(
id ),
754 len = ___strip_crs( str );
755 __kmp_str_buf_cat( & buffer, str, len );
762 __kmp_str_buf_detach( & buffer );
764 msg.type = (kmp_msg_type_t)(
id >> 16 );
765 msg.num =
id & 0xFFFF;
766 msg.str = buffer.str;
767 msg.len = buffer.used;
781 char * message = NULL;
785 LPVOID buffer = NULL;
790 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
793 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
800 message = __kmp_str_format(
"%s", (
char *) buffer );
801 len = ___strip_crs( message );
803 while ( len > 0 && message[ len - 1 ] ==
'\n' ) {
812 if ( buffer != NULL ) {
816 #else // Non-Windows* OS: Linux* OS or OS X*
830 char *
const err_msg = strerror_r( err, buffer,
sizeof( buffer ) );
833 message = __kmp_str_format(
"%s", err_msg );
835 #else // OS X*, FreeBSD* etc.
841 char * buffer = (
char *) KMP_INTERNAL_MALLOC( size );
843 rc = strerror_r( err, buffer, size );
847 while ( rc == ERANGE ) {
848 KMP_INTERNAL_FREE( buffer );
850 buffer = (
char *) KMP_INTERNAL_MALLOC( size );
851 rc = strerror_r( err, buffer, size );
860 KMP_INTERNAL_FREE( buffer );
867 if ( message == NULL ) {
869 message = __kmp_str_format(
"%s",
"(No system error message available)" );
878 __kmp_msg_error_code(
883 msg.type = kmp_mt_syserr;
885 msg.str = sys_error( code );
886 msg.len = KMP_STRLEN( msg.str );
894 __kmp_msg_error_mesg(
899 msg.type = kmp_mt_syserr;
901 msg.str = __kmp_str_format(
"%s", mesg );
902 msg.len = KMP_STRLEN( msg.str );
911 kmp_msg_severity_t severity,
917 kmp_i18n_id_t format;
919 kmp_str_buf_t buffer;
921 if ( severity != kmp_ms_fatal && __kmp_generate_warnings == kmp_warnings_off )
924 __kmp_str_buf_init( & buffer );
927 switch ( severity ) {
928 case kmp_ms_inform : {
929 format = kmp_i18n_fmt_Info;
931 case kmp_ms_warning : {
932 format = kmp_i18n_fmt_Warning;
934 case kmp_ms_fatal : {
935 format = kmp_i18n_fmt_Fatal;
938 KMP_DEBUG_ASSERT( 0 );
941 fmsg = __kmp_msg_format( format, message.num, message.str );
942 KMP_INTERNAL_FREE( (
void *) message.str );
943 __kmp_str_buf_cat( & buffer, fmsg.str, fmsg.len );
944 KMP_INTERNAL_FREE( (
void *) fmsg.str );
947 va_start( args, message );
949 message = va_arg( args, kmp_msg_t );
950 if ( message.type == kmp_mt_dummy && message.str == NULL ) {
953 if ( message.type == kmp_mt_dummy && message.str == __kmp_msg_empty.str ) {
956 switch ( message.type ) {
958 format = kmp_i18n_fmt_Hint;
960 case kmp_mt_syserr : {
961 format = kmp_i18n_fmt_SysErr;
964 KMP_DEBUG_ASSERT( 0 );
967 fmsg = __kmp_msg_format( format, message.num, message.str );
968 KMP_INTERNAL_FREE( (
void *) message.str );
969 __kmp_str_buf_cat( & buffer, fmsg.str, fmsg.len );
970 KMP_INTERNAL_FREE( (
void *) fmsg.str );
977 __kmp_printf(
"%s", buffer.str );
978 __kmp_str_buf_free( & buffer );
980 if ( severity == kmp_ms_fatal ) {
982 __kmp_thread_sleep( 500 );
984 __kmp_abort_process();