diff options
Diffstat (limited to 'openmp/runtime/src/kmp_i18n.cpp')
-rw-r--r-- | openmp/runtime/src/kmp_i18n.cpp | 1587 |
1 files changed, 728 insertions, 859 deletions
diff --git a/openmp/runtime/src/kmp_i18n.cpp b/openmp/runtime/src/kmp_i18n.cpp index 992d1fedea2..e542ea73de3 100644 --- a/openmp/runtime/src/kmp_i18n.cpp +++ b/openmp/runtime/src/kmp_i18n.cpp @@ -13,247 +13,208 @@ //===----------------------------------------------------------------------===// - #include "kmp_i18n.h" -#include "kmp_os.h" -#include "kmp_debug.h" #include "kmp.h" +#include "kmp_debug.h" +#include "kmp_io.h" // __kmp_printf. #include "kmp_lock.h" -#include "kmp_io.h" // __kmp_printf. +#include "kmp_os.h" -#include <stdio.h> #include <errno.h> -#include <string.h> #include <locale.h> #include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include "kmp_environment.h" #include "kmp_i18n_default.inc" #include "kmp_str.h" -#include "kmp_environment.h" #undef KMP_I18N_OK -#define get_section( id ) ( (id) >> 16 ) -#define get_number( id ) ( (id) & 0xFFFF ) +#define get_section(id) ((id) >> 16) +#define get_number(id) ((id)&0xFFFF) -kmp_msg_t __kmp_msg_empty = { kmp_mt_dummy, 0, "", 0 }; -kmp_msg_t __kmp_msg_null = { kmp_mt_dummy, 0, NULL, 0 }; -static char const * no_message_available = "(No message available)"; +kmp_msg_t __kmp_msg_empty = {kmp_mt_dummy, 0, "", 0}; +kmp_msg_t __kmp_msg_null = {kmp_mt_dummy, 0, NULL, 0}; +static char const *no_message_available = "(No message available)"; enum kmp_i18n_cat_status { - KMP_I18N_CLOSED, // Not yet opened or closed. - KMP_I18N_OPENED, // Opened successfully, ready to use. - KMP_I18N_ABSENT // Opening failed, message catalog should not be used. + KMP_I18N_CLOSED, // Not yet opened or closed. + KMP_I18N_OPENED, // Opened successfully, ready to use. + KMP_I18N_ABSENT // Opening failed, message catalog should not be used. }; // enum kmp_i18n_cat_status -typedef enum kmp_i18n_cat_status kmp_i18n_cat_status_t; -static volatile kmp_i18n_cat_status_t status = KMP_I18N_CLOSED; +typedef enum kmp_i18n_cat_status kmp_i18n_cat_status_t; +static volatile kmp_i18n_cat_status_t status = KMP_I18N_CLOSED; -/* - Message catalog is opened at first usage, so we have to synchronize opening to avoid race and - multiple openings. +/* Message catalog is opened at first usage, so we have to synchronize opening + to avoid race and multiple openings. - Closing does not require synchronization, because catalog is closed very late at library - shutting down, when no other threads are alive. -*/ + Closing does not require synchronization, because catalog is closed very late + at library shutting down, when no other threads are alive. */ static void __kmp_i18n_do_catopen(); -static kmp_bootstrap_lock_t lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( lock ); - // `lock' variable may be placed into __kmp_i18n_catopen function because it is used only by - // that function. But we afraid a (buggy) compiler may treat it wrongly. So we put it outside of - // function just in case. - -void -__kmp_i18n_catopen( -) { - if ( status == KMP_I18N_CLOSED ) { - __kmp_acquire_bootstrap_lock( & lock ); - if ( status == KMP_I18N_CLOSED ) { - __kmp_i18n_do_catopen(); - }; // if - __kmp_release_bootstrap_lock( & lock ); +static kmp_bootstrap_lock_t lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(lock); +// `lock' variable may be placed into __kmp_i18n_catopen function because it is +// used only by that function. But we afraid a (buggy) compiler may treat it +// wrongly. So we put it outside of function just in case. + +void __kmp_i18n_catopen() { + if (status == KMP_I18N_CLOSED) { + __kmp_acquire_bootstrap_lock(&lock); + if (status == KMP_I18N_CLOSED) { + __kmp_i18n_do_catopen(); }; // if + __kmp_release_bootstrap_lock(&lock); + }; // if } // func __kmp_i18n_catopen - -/* - ================================================================================================ - Linux* OS and OS X* part. - ================================================================================================ -*/ - +/* Linux* OS and OS X* part */ #if KMP_OS_UNIX #define KMP_I18N_OK #include <nl_types.h> -#define KMP_I18N_NULLCAT ((nl_catd)( -1 )) -static nl_catd cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile? -static char const * name = ( KMP_VERSION_MAJOR == 4 ? "libguide.cat" : "libomp.cat" ); +#define KMP_I18N_NULLCAT ((nl_catd)(-1)) +static nl_catd cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile? +static char const *name = + (KMP_VERSION_MAJOR == 4 ? "libguide.cat" : "libomp.cat"); -/* - Useful links: - http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html#tag_08_02 - http://www.opengroup.org/onlinepubs/000095399/functions/catopen.html - http://www.opengroup.org/onlinepubs/000095399/functions/setlocale.html +/* Useful links: +http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html#tag_08_02 +http://www.opengroup.org/onlinepubs/000095399/functions/catopen.html +http://www.opengroup.org/onlinepubs/000095399/functions/setlocale.html */ -void -__kmp_i18n_do_catopen( -) { - int english = 0; - char * lang = __kmp_env_get( "LANG" ); - // TODO: What about LC_ALL or LC_MESSAGES? - - KMP_DEBUG_ASSERT( status == KMP_I18N_CLOSED ); - KMP_DEBUG_ASSERT( cat == KMP_I18N_NULLCAT ); - - english = - lang == NULL || // In all these cases English language is used. - strcmp( lang, "" ) == 0 || - strcmp( lang, " " ) == 0 || - // Workaround for Fortran RTL bug DPD200137873 "Fortran runtime resets LANG env var - // to space if it is not set". - strcmp( lang, "C" ) == 0 || - strcmp( lang, "POSIX" ) == 0; - - if ( ! english ) { // English language is not yet detected, let us continue. - // Format of LANG is: [language[_territory][.codeset][@modifier]] - // Strip all parts except language. - char * tail = NULL; - __kmp_str_split( lang, '@', & lang, & tail ); - __kmp_str_split( lang, '.', & lang, & tail ); - __kmp_str_split( lang, '_', & lang, & tail ); - english = ( strcmp( lang, "en" ) == 0 ); - }; // if - - KMP_INTERNAL_FREE( lang ); +void __kmp_i18n_do_catopen() { + int english = 0; + char *lang = __kmp_env_get("LANG"); + // TODO: What about LC_ALL or LC_MESSAGES? + + KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED); + KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT); + + english = lang == NULL || // In all these cases English language is used. + strcmp(lang, "") == 0 || strcmp(lang, " ") == 0 || + // Workaround for Fortran RTL bug DPD200137873 "Fortran runtime + // resets LANG env var to space if it is not set". + strcmp(lang, "C") == 0 || strcmp(lang, "POSIX") == 0; + + if (!english) { // English language is not yet detected, let us continue. + // Format of LANG is: [language[_territory][.codeset][@modifier]] + // Strip all parts except language. + char *tail = NULL; + __kmp_str_split(lang, '@', &lang, &tail); + __kmp_str_split(lang, '.', &lang, &tail); + __kmp_str_split(lang, '_', &lang, &tail); + english = (strcmp(lang, "en") == 0); + }; // if + + KMP_INTERNAL_FREE(lang); + + // Do not try to open English catalog because internal messages are + // exact copy of messages in English catalog. + if (english) { + status = KMP_I18N_ABSENT; // mark catalog as absent so it will not + // be re-opened. + return; + } + + cat = catopen(name, 0); + // TODO: Why do we pass 0 in flags? + status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED); + + if (status == KMP_I18N_ABSENT) { + if (__kmp_generate_warnings > kmp_warnings_low) { + // AC: only issue warning in case explicitly asked to + int error = errno; // Save errno immediately. + char *nlspath = __kmp_env_get("NLSPATH"); + char *lang = __kmp_env_get("LANG"); + + // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so + // __kmp_i18n_catgets() will not try to open catalog, but will return + // default message. + kmp_msg_t err_code = KMP_ERR(error); + __kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, name), err_code, + KMP_HNT(CheckEnvVar, "NLSPATH", nlspath), + KMP_HNT(CheckEnvVar, "LANG", lang), __kmp_msg_null); + if (__kmp_generate_warnings == kmp_warnings_off) { + __kmp_str_free(&err_code.str); + } - // Do not try to open English catalog because internal messages are - // exact copy of messages in English catalog. - if ( english ) { - status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be re-opened. - return; + KMP_INFORM(WillUseDefaultMessages); + KMP_INTERNAL_FREE(nlspath); + KMP_INTERNAL_FREE(lang); } - - cat = catopen( name, 0 ); - // TODO: Why do we pass 0 in flags? - status = ( cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED ); - - if ( status == KMP_I18N_ABSENT ) { - if (__kmp_generate_warnings > kmp_warnings_low) { // AC: only issue warning in case explicitly asked to - int error = errno; // Save errno immediately. - char * nlspath = __kmp_env_get( "NLSPATH" ); - char * lang = __kmp_env_get( "LANG" ); - - // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so - // __kmp_i18n_catgets() will not try to open catalog, but will return default message. - kmp_msg_t err_code = KMP_ERR( error ); - __kmp_msg( - kmp_ms_warning, - KMP_MSG( CantOpenMessageCatalog, name ), - err_code, - KMP_HNT( CheckEnvVar, "NLSPATH", nlspath ), - KMP_HNT( CheckEnvVar, "LANG", lang ), - __kmp_msg_null - ); - if (__kmp_generate_warnings == kmp_warnings_off) { - __kmp_str_free(&err_code.str); - } - - KMP_INFORM( WillUseDefaultMessages ); - KMP_INTERNAL_FREE( nlspath ); - KMP_INTERNAL_FREE( lang ); - } - } else { // status == KMP_I18N_OPENED - - int section = get_section( kmp_i18n_prp_Version ); - int number = get_number( kmp_i18n_prp_Version ); - char const * expected = __kmp_i18n_default_table.sect[ section ].str[ number ]; - // Expected version of the catalog. - kmp_str_buf_t version; // Actual version of the catalog. - __kmp_str_buf_init( & version ); - __kmp_str_buf_print( & version, "%s", catgets( cat, section, number, NULL ) ); - - // String returned by catgets is invalid after closing the catalog, so copy it. - if ( strcmp( version.str, expected ) != 0 ) { - __kmp_i18n_catclose(); // Close bad catalog. - status = KMP_I18N_ABSENT; // And mark it as absent. - if (__kmp_generate_warnings > kmp_warnings_low) { // AC: only issue warning in case explicitly asked to - // And now print a warning using default messages. - char const * name = "NLSPATH"; - char const * nlspath = __kmp_env_get( name ); - __kmp_msg( - kmp_ms_warning, - KMP_MSG( WrongMessageCatalog, name, version.str, expected ), - KMP_HNT( CheckEnvVar, name, nlspath ), - __kmp_msg_null - ); - KMP_INFORM( WillUseDefaultMessages ); - KMP_INTERNAL_FREE( (void *) nlspath ); - } // __kmp_generate_warnings - }; // if - __kmp_str_buf_free( & version ); - + } else { // status == KMP_I18N_OPENED + int section = get_section(kmp_i18n_prp_Version); + int number = get_number(kmp_i18n_prp_Version); + char const *expected = __kmp_i18n_default_table.sect[section].str[number]; + // Expected version of the catalog. + kmp_str_buf_t version; // Actual version of the catalog. + __kmp_str_buf_init(&version); + __kmp_str_buf_print(&version, "%s", catgets(cat, section, number, NULL)); + + // String returned by catgets is invalid after closing catalog, so copy it. + if (strcmp(version.str, expected) != 0) { + __kmp_i18n_catclose(); // Close bad catalog. + status = KMP_I18N_ABSENT; // And mark it as absent. + if (__kmp_generate_warnings > kmp_warnings_low) { + // AC: only issue warning in case explicitly asked to + // And now print a warning using default messages. + char const *name = "NLSPATH"; + char const *nlspath = __kmp_env_get(name); + __kmp_msg(kmp_ms_warning, + KMP_MSG(WrongMessageCatalog, name, version.str, expected), + KMP_HNT(CheckEnvVar, name, nlspath), __kmp_msg_null); + KMP_INFORM(WillUseDefaultMessages); + KMP_INTERNAL_FREE((void *)nlspath); + } // __kmp_generate_warnings }; // if - + __kmp_str_buf_free(&version); + }; // if } // func __kmp_i18n_do_catopen - -void -__kmp_i18n_catclose( -) { - if ( status == KMP_I18N_OPENED ) { - KMP_DEBUG_ASSERT( cat != KMP_I18N_NULLCAT ); - catclose( cat ); - cat = KMP_I18N_NULLCAT; - }; // if - status = KMP_I18N_CLOSED; +void __kmp_i18n_catclose() { + if (status == KMP_I18N_OPENED) { + KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT); + catclose(cat); + cat = KMP_I18N_NULLCAT; + }; // if + status = KMP_I18N_CLOSED; } // func __kmp_i18n_catclose - -char const * -__kmp_i18n_catgets( - kmp_i18n_id_t id -) { - - int section = get_section( id ); - int number = get_number( id ); - char const * message = NULL; - - if ( 1 <= section && section <= __kmp_i18n_default_table.size ) { - if ( 1 <= number && number <= __kmp_i18n_default_table.sect[ section ].size ) { - if ( status == KMP_I18N_CLOSED ) { - __kmp_i18n_catopen(); - }; // if - if ( status == KMP_I18N_OPENED ) { - message = - catgets( - cat, - section, number, - __kmp_i18n_default_table.sect[ section ].str[ number ] - ); - }; // if - if ( message == NULL ) { - message = __kmp_i18n_default_table.sect[ section ].str[ number ]; - }; // if - }; // if - }; // if - if ( message == NULL ) { - message = no_message_available; +char const *__kmp_i18n_catgets(kmp_i18n_id_t id) { + + int section = get_section(id); + int number = get_number(id); + char const *message = NULL; + + if (1 <= section && section <= __kmp_i18n_default_table.size) { + if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) { + if (status == KMP_I18N_CLOSED) { + __kmp_i18n_catopen(); + }; // if + if (status == KMP_I18N_OPENED) { + message = catgets(cat, section, number, + __kmp_i18n_default_table.sect[section].str[number]); + }; // if + if (message == NULL) { + message = __kmp_i18n_default_table.sect[section].str[number]; + }; // if }; // if - return message; + }; // if + if (message == NULL) { + message = no_message_available; + }; // if + return message; } // func __kmp_i18n_catgets - #endif // KMP_OS_UNIX -/* - ================================================================================================ - Windows* OS part. - ================================================================================================ -*/ +/* Windows* OS part. */ #if KMP_OS_WINDOWS #define KMP_I18N_OK @@ -261,737 +222,645 @@ __kmp_i18n_catgets( #include "kmp_environment.h" #include <windows.h> -#define KMP_I18N_NULLCAT NULL -static HMODULE cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile? -static char const * name = ( KMP_VERSION_MAJOR == 4 ? "libguide40ui.dll" : "libompui.dll" ); - -static kmp_i18n_table_t table = { 0, NULL }; - // Messages formatted by FormatMessage() should be freed, but catgets() interface assumes - // user will not free messages. So we cache all the retrieved messages in the table, which - // are freed at catclose(). -static UINT const default_code_page = CP_OEMCP; -static UINT code_page = default_code_page; - -static char const * ___catgets( kmp_i18n_id_t id ); -static UINT get_code_page(); -static void kmp_i18n_table_free( kmp_i18n_table_t * table ); - - -static UINT -get_code_page( -) { - - UINT cp = default_code_page; - char const * value = __kmp_env_get( "KMP_CODEPAGE" ); - if ( value != NULL ) { - if ( _stricmp( value, "ANSI" ) == 0 ) { - cp = CP_ACP; - } else if ( _stricmp( value, "OEM" ) == 0 ) { - cp = CP_OEMCP; - } else if ( _stricmp( value, "UTF-8" ) == 0 || _stricmp( value, "UTF8" ) == 0 ) { - cp = CP_UTF8; - } else if ( _stricmp( value, "UTF-7" ) == 0 || _stricmp( value, "UTF7" ) == 0 ) { - cp = CP_UTF7; - } else { - // !!! TODO: Issue a warning? - }; // if +#define KMP_I18N_NULLCAT NULL +static HMODULE cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile? +static char const *name = + (KMP_VERSION_MAJOR == 4 ? "libguide40ui.dll" : "libompui.dll"); + +static kmp_i18n_table_t table = {0, NULL}; +// Messages formatted by FormatMessage() should be freed, but catgets() +// interface assumes user will not free messages. So we cache all the retrieved +// messages in the table, which are freed at catclose(). +static UINT const default_code_page = CP_OEMCP; +static UINT code_page = default_code_page; + +static char const *___catgets(kmp_i18n_id_t id); +static UINT get_code_page(); +static void kmp_i18n_table_free(kmp_i18n_table_t *table); + +static UINT get_code_page() { + + UINT cp = default_code_page; + char const *value = __kmp_env_get("KMP_CODEPAGE"); + if (value != NULL) { + if (_stricmp(value, "ANSI") == 0) { + cp = CP_ACP; + } else if (_stricmp(value, "OEM") == 0) { + cp = CP_OEMCP; + } else if (_stricmp(value, "UTF-8") == 0 || _stricmp(value, "UTF8") == 0) { + cp = CP_UTF8; + } else if (_stricmp(value, "UTF-7") == 0 || _stricmp(value, "UTF7") == 0) { + cp = CP_UTF7; + } else { + // !!! TODO: Issue a warning? }; // if - KMP_INTERNAL_FREE( (void *) value ); - return cp; + }; // if + KMP_INTERNAL_FREE((void *)value); + return cp; } // func get_code_page - -static void -kmp_i18n_table_free( - kmp_i18n_table_t * table -) { - int s; - int m; - for ( s = 0; s < table->size; ++ s ) { - for ( m = 0; m < table->sect[ s ].size; ++ m ) { - // Free message. - KMP_INTERNAL_FREE( (void *) table->sect[ s ].str[ m ] ); - table->sect[ s ].str[ m ] = NULL; - }; // for m - table->sect[ s ].size = 0; - // Free section itself. - KMP_INTERNAL_FREE ( (void *) table->sect[ s ].str ); - table->sect[ s ].str = NULL; - }; // for s - table->size = 0; - KMP_INTERNAL_FREE( (void *) table->sect ); - table->sect = NULL; +static void kmp_i18n_table_free(kmp_i18n_table_t *table) { + int s; + int m; + for (s = 0; s < table->size; ++s) { + for (m = 0; m < table->sect[s].size; ++m) { + // Free message. + KMP_INTERNAL_FREE((void *)table->sect[s].str[m]); + table->sect[s].str[m] = NULL; + }; // for m + table->sect[s].size = 0; + // Free section itself. + KMP_INTERNAL_FREE((void *)table->sect[s].str); + table->sect[s].str = NULL; + }; // for s + table->size = 0; + KMP_INTERNAL_FREE((void *)table->sect); + table->sect = NULL; } // kmp_i18n_table_free - -void -__kmp_i18n_do_catopen( -) { - - LCID locale_id = GetThreadLocale(); - WORD lang_id = LANGIDFROMLCID( locale_id ); - WORD primary_lang_id = PRIMARYLANGID( lang_id ); - kmp_str_buf_t path; - - KMP_DEBUG_ASSERT( status == KMP_I18N_CLOSED ); - KMP_DEBUG_ASSERT( cat == KMP_I18N_NULLCAT ); - - __kmp_str_buf_init( & path ); - - // Do not try to open English catalog because internal messages are - // exact copy of messages in English catalog. - if ( primary_lang_id == LANG_ENGLISH ) { - status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be re-opened. - goto end; +void __kmp_i18n_do_catopen() { + + LCID locale_id = GetThreadLocale(); + WORD lang_id = LANGIDFROMLCID(locale_id); + WORD primary_lang_id = PRIMARYLANGID(lang_id); + kmp_str_buf_t path; + + KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED); + KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT); + + __kmp_str_buf_init(&path); + + // Do not try to open English catalog because internal messages are exact copy + // of messages in English catalog. + if (primary_lang_id == LANG_ENGLISH) { + status = KMP_I18N_ABSENT; // mark catalog as absent so it will not + // be re-opened. + goto end; + }; // if + + // Construct resource DLL name. + /* Simple LoadLibrary( name ) is not suitable due to security issue (see + http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have + to specify full path to the message catalog. */ + { + // Get handle of our DLL first. + HMODULE handle; + BOOL brc = GetModuleHandleEx( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast<LPCSTR>(&__kmp_i18n_do_catopen), &handle); + if (!brc) { // Error occurred. + status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be + // re-opened. + goto end; + // TODO: Enable multiple messages (KMP_MSG) to be passed to __kmp_msg; and + // print a proper warning. }; // if - // Construct resource DLL name. - /* - Simple - LoadLibrary( name ) - is not suitable due to security issue (see - http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have to specify full - path to the message catalog. - */ - { - - // Get handle of our DLL first. - HMODULE handle; - BOOL brc = - GetModuleHandleEx( - GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - reinterpret_cast< LPCSTR >( & __kmp_i18n_do_catopen ), - & handle - ); - if ( ! brc ) { // Error occurred. - status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be re-opened. - goto end; - // TODO: Enable multiple messages (KMP_MSG) to be passed to __kmp_msg; and print - // a proper warning. - }; // if - - // Now get path to the our DLL. - for ( ; ; ) { - DWORD drc = GetModuleFileName( handle, path.str, path.size ); - if ( drc == 0 ) { // Error occurred. - status = KMP_I18N_ABSENT; - goto end; - }; // if - if ( drc < path.size ) { - path.used = drc; - break; - }; // if - __kmp_str_buf_reserve( & path, path.size * 2 ); - }; // forever - - // Now construct the name of message catalog. - kmp_str_fname fname; - __kmp_str_fname_init( & fname, path.str ); - __kmp_str_buf_clear( & path ); - __kmp_str_buf_print( & path, "%s%lu/%s", fname.dir, (unsigned long)( locale_id ), name ); - __kmp_str_fname_free( & fname ); - - } + // Now get path to the our DLL. + for (;;) { + DWORD drc = GetModuleFileName(handle, path.str, path.size); + if (drc == 0) { // Error occurred. + status = KMP_I18N_ABSENT; + goto end; + }; // if + if (drc < path.size) { + path.used = drc; + break; + }; // if + __kmp_str_buf_reserve(&path, path.size * 2); + }; // forever - // For security reasons, use LoadLibraryEx() and load message catalog as a data file. - cat = LoadLibraryEx( path.str, NULL, LOAD_LIBRARY_AS_DATAFILE ); - status = ( cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED ); - - if ( status == KMP_I18N_ABSENT ) { - if (__kmp_generate_warnings > kmp_warnings_low) { // AC: only issue warning in case explicitly asked to - DWORD error = GetLastError(); - // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so - // __kmp_i18n_catgets() will not try to open catalog but will return default message. - /* - If message catalog for another architecture found (e.g. OpenMP RTL - for IA-32 architecture opens libompui.dll for Intel(R) 64) - Windows* OS returns error 193 (ERROR_BAD_EXE_FORMAT). However, - FormatMessage fails to return a message for this error, so user - will see: - - OMP: Warning #2: Cannot open message catalog "1041\libompui.dll": - OMP: System error #193: (No system error message available) - OMP: Info #3: Default messages will be used. - - Issue a hint in this case to let cause of trouble more understandable. - */ - kmp_msg_t err_code = KMP_SYSERRCODE(error); - __kmp_msg( - kmp_ms_warning, - KMP_MSG( CantOpenMessageCatalog, path.str ), - err_code, - ( error == ERROR_BAD_EXE_FORMAT ? KMP_HNT( BadExeFormat, path.str, KMP_ARCH_STR ) : __kmp_msg_null ), - __kmp_msg_null - ); - if (__kmp_generate_warnings == kmp_warnings_off) { - __kmp_str_free(&err_code.str); - } - - KMP_INFORM( WillUseDefaultMessages ); + // Now construct the name of message catalog. + kmp_str_fname fname; + __kmp_str_fname_init(&fname, path.str); + __kmp_str_buf_clear(&path); + __kmp_str_buf_print(&path, "%s%lu/%s", fname.dir, + (unsigned long)(locale_id), name); + __kmp_str_fname_free(&fname); + } + + // For security reasons, use LoadLibraryEx() and load message catalog as a + // data file. + cat = LoadLibraryEx(path.str, NULL, LOAD_LIBRARY_AS_DATAFILE); + status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED); + + if (status == KMP_I18N_ABSENT) { + if (__kmp_generate_warnings > kmp_warnings_low) { + // AC: only issue warning in case explicitly asked to + DWORD error = GetLastError(); + // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so + // __kmp_i18n_catgets() will not try to open catalog but will return + // default message. + /* If message catalog for another architecture found (e.g. OpenMP RTL for + IA-32 architecture opens libompui.dll for Intel(R) 64) Windows* OS + returns error 193 (ERROR_BAD_EXE_FORMAT). However, FormatMessage fails + to return a message for this error, so user will see: + + OMP: Warning #2: Cannot open message catalog "1041\libompui.dll": + OMP: System error #193: (No system error message available) + OMP: Info #3: Default messages will be used. + + Issue hint in this case so cause of trouble is more understandable. */ + kmp_msg_t err_code = KMP_SYSERRCODE(error); + __kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, path.str), + err_code, (error == ERROR_BAD_EXE_FORMAT + ? KMP_HNT(BadExeFormat, path.str, KMP_ARCH_STR) + : __kmp_msg_null), + __kmp_msg_null); + if (__kmp_generate_warnings == kmp_warnings_off) { + __kmp_str_free(&err_code.str); } - } else { // status == KMP_I18N_OPENED - - int section = get_section( kmp_i18n_prp_Version ); - int number = get_number( kmp_i18n_prp_Version ); - char const * expected = __kmp_i18n_default_table.sect[ section ].str[ number ]; - kmp_str_buf_t version; // Actual version of the catalog. - __kmp_str_buf_init( & version ); - __kmp_str_buf_print( & version, "%s", ___catgets( kmp_i18n_prp_Version ) ); - // String returned by catgets is invalid after closing the catalog, so copy it. - if ( strcmp( version.str, expected ) != 0 ) { - // Close bad catalog. - __kmp_i18n_catclose(); - status = KMP_I18N_ABSENT; // And mark it as absent. - if (__kmp_generate_warnings > kmp_warnings_low) { - // And now print a warning using default messages. - __kmp_msg( - kmp_ms_warning, - KMP_MSG( WrongMessageCatalog, path.str, version.str, expected ), - __kmp_msg_null - ); - KMP_INFORM( WillUseDefaultMessages ); - } // __kmp_generate_warnings - }; // if - __kmp_str_buf_free( & version ); - + KMP_INFORM(WillUseDefaultMessages); + } + } else { // status == KMP_I18N_OPENED + + int section = get_section(kmp_i18n_prp_Version); + int number = get_number(kmp_i18n_prp_Version); + char const *expected = __kmp_i18n_default_table.sect[section].str[number]; + kmp_str_buf_t version; // Actual version of the catalog. + __kmp_str_buf_init(&version); + __kmp_str_buf_print(&version, "%s", ___catgets(kmp_i18n_prp_Version)); + // String returned by catgets is invalid after closing catalog, so copy it. + if (strcmp(version.str, expected) != 0) { + // Close bad catalog. + __kmp_i18n_catclose(); + status = KMP_I18N_ABSENT; // And mark it as absent. + if (__kmp_generate_warnings > kmp_warnings_low) { + // And now print a warning using default messages. + __kmp_msg(kmp_ms_warning, + KMP_MSG(WrongMessageCatalog, path.str, version.str, expected), + __kmp_msg_null); + KMP_INFORM(WillUseDefaultMessages); + } // __kmp_generate_warnings }; // if - code_page = get_code_page(); + __kmp_str_buf_free(&version); - end: - __kmp_str_buf_free( & path ); - return; + }; // if + code_page = get_code_page(); +end: + __kmp_str_buf_free(&path); + return; } // func __kmp_i18n_do_catopen - -void -__kmp_i18n_catclose( -) { - if ( status == KMP_I18N_OPENED ) { - KMP_DEBUG_ASSERT( cat != KMP_I18N_NULLCAT ); - kmp_i18n_table_free( & table ); - FreeLibrary( cat ); - cat = KMP_I18N_NULLCAT; - }; // if - code_page = default_code_page; - status = KMP_I18N_CLOSED; +void __kmp_i18n_catclose() { + if (status == KMP_I18N_OPENED) { + KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT); + kmp_i18n_table_free(&table); + FreeLibrary(cat); + cat = KMP_I18N_NULLCAT; + }; // if + code_page = default_code_page; + status = KMP_I18N_CLOSED; } // func __kmp_i18n_catclose -/* - We use FormatMessage() to get strings from catalog, get system error messages, etc. - FormatMessage() tends to return Windows* OS-style end-of-lines, "\r\n". When string is printed, - printf() also replaces all the occurrences of "\n" with "\r\n" (again!), so sequences like - "\r\r\r\n" appear in output. It is not too good. +/* We use FormatMessage() to get strings from catalog, get system error + messages, etc. FormatMessage() tends to return Windows* OS-style + end-of-lines, "\r\n". When string is printed, printf() also replaces all the + occurrences of "\n" with "\r\n" (again!), so sequences like "\r\r\r\n" + appear in output. It is not too good. - Additional mess comes from message catalog: Our catalog source en_US.mc file (generated by - message-converter.pl) contains only "\n" characters, but en_US_msg_1033.bin file (produced by - mc.exe) may contain "\r\n" or just "\n". This mess goes from en_US_msg_1033.bin file to - message catalog, libompui.dll. For example, message + Additional mess comes from message catalog: Our catalog source en_US.mc file + (generated by message-converter.pl) contains only "\n" characters, but + en_US_msg_1033.bin file (produced by mc.exe) may contain "\r\n" or just "\n". + This mess goes from en_US_msg_1033.bin file to message catalog, + libompui.dll. For example, message - Error + Error - (there is "\n" at the end) is compiled by mc.exe to "Error\r\n", while + (there is "\n" at the end) is compiled by mc.exe to "Error\r\n", while - OMP: Error %1!d!: %2!s!\n + OMP: Error %1!d!: %2!s!\n - (there is "\n" at the end as well) is compiled to "OMP: Error %1!d!: %2!s!\r\n\n". + (there is "\n" at the end as well) is compiled to "OMP: Error %1!d!: + %2!s!\r\n\n". - Thus, stripping all "\r" normalizes string and returns it to canonical form, so printf() will - produce correct end-of-line sequences. + Thus, stripping all "\r" normalizes string and returns it to canonical form, + so printf() will produce correct end-of-line sequences. - ___strip_crs() serves for this purpose: it removes all the occurrences of "\r" in-place and - returns new length of string. -*/ -static -int -___strip_crs( - char * str -) { - int in = 0; // Input character index. - int out = 0; // Output character index. - for ( ; ; ) { - if ( str[ in ] != '\r' ) { - str[ out ] = str[ in ]; - ++ out; - }; // if - if ( str[ in ] == 0 ) { - break; - }; // if - ++ in; - }; // forever - return out - 1; + ___strip_crs() serves for this purpose: it removes all the occurrences of + "\r" in-place and returns new length of string. */ +static int ___strip_crs(char *str) { + int in = 0; // Input character index. + int out = 0; // Output character index. + for (;;) { + if (str[in] != '\r') { + str[out] = str[in]; + ++out; + }; // if + if (str[in] == 0) { + break; + }; // if + ++in; + }; // forever + return out - 1; } // func __strip_crs +static char const *___catgets(kmp_i18n_id_t id) { + + char *result = NULL; + PVOID addr = NULL; + wchar_t *wmsg = NULL; + DWORD wlen = 0; + char *msg = NULL; + int len = 0; + int rc; + + KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT); + wlen = // wlen does *not* include terminating null. + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_IGNORE_INSERTS, + cat, id, + 0, // LangId + (LPWSTR)&addr, + 0, // Size in elements, not in bytes. + NULL); + if (wlen <= 0) { + goto end; + }; // if + wmsg = (wchar_t *)addr; // Warning: wmsg may be not nul-terminated! + + // Calculate length of multibyte message. + // Since wlen does not include terminating null, len does not include it also. + len = WideCharToMultiByte(code_page, + 0, // Flags. + wmsg, wlen, // Wide buffer and size. + NULL, 0, // Buffer and size. + NULL, NULL // Default char and used default char. + ); + if (len <= 0) { + goto end; + }; // if + + // Allocate memory. + msg = (char *)KMP_INTERNAL_MALLOC(len + 1); + + // Convert wide message to multibyte one. + rc = WideCharToMultiByte(code_page, + 0, // Flags. + wmsg, wlen, // Wide buffer and size. + msg, len, // Buffer and size. + NULL, NULL // Default char and used default char. + ); + if (rc <= 0 || rc > len) { + goto end; + }; // if + KMP_DEBUG_ASSERT(rc == len); + len = rc; + msg[len] = 0; // Put terminating null to the end. + + // Stripping all "\r" before stripping last end-of-line simplifies the task. + len = ___strip_crs(msg); + + // Every message in catalog is terminated with "\n". Strip it. + if (len >= 1 && msg[len - 1] == '\n') { + --len; + msg[len] = 0; + }; // if + + // Everything looks ok. + result = msg; + msg = NULL; + +end: + + if (msg != NULL) { + KMP_INTERNAL_FREE(msg); + }; // if + if (wmsg != NULL) { + LocalFree(wmsg); + }; // if + + return result; -static -char const * -___catgets( - kmp_i18n_id_t id -) { - - char * result = NULL; - PVOID addr = NULL; - wchar_t * wmsg = NULL; - DWORD wlen = 0; - char * msg = NULL; - int len = 0; - int rc; - - KMP_DEBUG_ASSERT( cat != KMP_I18N_NULLCAT ); - wlen = // wlen does *not* include terminating null. - FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | - FORMAT_MESSAGE_IGNORE_INSERTS, - cat, - id, - 0, // LangId - (LPWSTR) & addr, - 0, // Size in elements, not in bytes. - NULL - ); - if ( wlen <= 0 ) { - goto end; - }; // if - wmsg = (wchar_t *) addr; // Warning: wmsg may be not nul-terminated! - - // Calculate length of multibyte message. - len = // Since wlen does not include terminating null, len does not include it also. - WideCharToMultiByte( - code_page, - 0, // Flags. - wmsg, wlen, // Wide buffer and size. - NULL, 0, // Buffer and size. - NULL, NULL // Default char and used default char. - ); - if ( len <= 0 ) { - goto end; - }; // if +} // ___catgets - // Allocate memory. - msg = (char *) KMP_INTERNAL_MALLOC( len + 1 ); - - // Convert wide message to multibyte one. - rc = - WideCharToMultiByte( - code_page, - 0, // Flags. - wmsg, wlen, // Wide buffer and size. - msg, len, // Buffer and size. - NULL, NULL // Default char and used default char. - ); - if ( rc <= 0 || rc > len ) { - goto end; +char const *__kmp_i18n_catgets(kmp_i18n_id_t id) { + + int section = get_section(id); + int number = get_number(id); + char const *message = NULL; + + if (1 <= section && section <= __kmp_i18n_default_table.size) { + if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) { + if (status == KMP_I18N_CLOSED) { + __kmp_i18n_catopen(); + }; // if + if (cat != KMP_I18N_NULLCAT) { + if (table.size == 0) { + table.sect = (kmp_i18n_section_t *)KMP_INTERNAL_CALLOC( + (__kmp_i18n_default_table.size + 2), sizeof(kmp_i18n_section_t)); + table.size = __kmp_i18n_default_table.size; + }; // if + if (table.sect[section].size == 0) { + table.sect[section].str = (const char **)KMP_INTERNAL_CALLOC( + __kmp_i18n_default_table.sect[section].size + 2, + sizeof(char const *)); + table.sect[section].size = + __kmp_i18n_default_table.sect[section].size; + }; // if + if (table.sect[section].str[number] == NULL) { + table.sect[section].str[number] = ___catgets(id); + }; // if + message = table.sect[section].str[number]; + }; // if + if (message == NULL) { + // Catalog is not opened or message is not found, return default + // message. + message = __kmp_i18n_default_table.sect[section].str[number]; + }; // if }; // if - KMP_DEBUG_ASSERT( rc == len ); - len = rc; - msg[ len ] = 0; // Put terminating null to the end. + }; // if + if (message == NULL) { + message = no_message_available; + }; // if + return message; - // Stripping all "\r" before stripping last end-of-line simplifies the task. - len = ___strip_crs( msg ); +} // func __kmp_i18n_catgets - // Every message in catalog is terminated with "\n". Strip it. - if ( len >= 1 && msg[ len - 1 ] == '\n' ) { - -- len; - msg[ len ] = 0; - }; // if +#endif // KMP_OS_WINDOWS - // Everything looks ok. - result = msg; - msg = NULL; +// ----------------------------------------------------------------------------- - end: +#ifndef KMP_I18N_OK +#error I18n support is not implemented for this OS. +#endif // KMP_I18N_OK - if ( msg != NULL ) { - KMP_INTERNAL_FREE( msg ); - }; // if - if ( wmsg != NULL ) { - LocalFree( wmsg ); - }; // if +// ----------------------------------------------------------------------------- - return result; +void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer) { -} // ___catgets + struct kmp_i18n_id_range_t { + kmp_i18n_id_t first; + kmp_i18n_id_t last; + }; // struct kmp_i18n_id_range_t + static struct kmp_i18n_id_range_t ranges[] = { + {kmp_i18n_prp_first, kmp_i18n_prp_last}, + {kmp_i18n_str_first, kmp_i18n_str_last}, + {kmp_i18n_fmt_first, kmp_i18n_fmt_last}, + {kmp_i18n_msg_first, kmp_i18n_msg_last}, + {kmp_i18n_hnt_first, kmp_i18n_hnt_last}}; // ranges -char const * -__kmp_i18n_catgets( - kmp_i18n_id_t id -) { - - int section = get_section( id ); - int number = get_number( id ); - char const * message = NULL; - - if ( 1 <= section && section <= __kmp_i18n_default_table.size ) { - if ( 1 <= number && number <= __kmp_i18n_default_table.sect[ section ].size ) { - if ( status == KMP_I18N_CLOSED ) { - __kmp_i18n_catopen(); - }; // if - if ( cat != KMP_I18N_NULLCAT ) { - if ( table.size == 0 ) { - table.sect = (kmp_i18n_section_t *) - KMP_INTERNAL_CALLOC( - ( __kmp_i18n_default_table.size + 2 ), - sizeof( kmp_i18n_section_t ) - ); - table.size = __kmp_i18n_default_table.size; - }; // if - if ( table.sect[ section ].size == 0 ) { - table.sect[ section ].str = (const char **) - KMP_INTERNAL_CALLOC( - __kmp_i18n_default_table.sect[ section ].size + 2, - sizeof( char const * ) - ); - table.sect[ section ].size = __kmp_i18n_default_table.sect[ section ].size; - }; // if - if ( table.sect[ section ].str[ number ] == NULL ) { - table.sect[ section ].str[ number ] = ___catgets( id ); - }; // if - message = table.sect[ section ].str[ number ]; - }; // if - if ( message == NULL ) { - // Catalog is not opened or message is not found, return default message. - message = __kmp_i18n_default_table.sect[ section ].str[ number ]; - }; // if - }; // if - }; // if - if ( message == NULL ) { - message = no_message_available; - }; // if - return message; + int num_of_ranges = sizeof(ranges) / sizeof(struct kmp_i18n_id_range_t); + int range; + kmp_i18n_id_t id; -} // func __kmp_i18n_catgets + for (range = 0; range < num_of_ranges; ++range) { + __kmp_str_buf_print(buffer, "*** Set #%d ***\n", range + 1); + for (id = (kmp_i18n_id_t)(ranges[range].first + 1); id < ranges[range].last; + id = (kmp_i18n_id_t)(id + 1)) { + __kmp_str_buf_print(buffer, "%d: <<%s>>\n", id, __kmp_i18n_catgets(id)); + }; // for id + }; // for range + __kmp_printf("%s", buffer->str); -#endif // KMP_OS_WINDOWS +} // __kmp_i18n_dump_catalog -// ------------------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +kmp_msg_t __kmp_msg_format(unsigned id_arg, ...) { -#ifndef KMP_I18N_OK - #error I18n support is not implemented for this OS. -#endif // KMP_I18N_OK + kmp_msg_t msg; + va_list args; + kmp_str_buf_t buffer; + __kmp_str_buf_init(&buffer); -// ------------------------------------------------------------------------------------------------- - -void -__kmp_i18n_dump_catalog( - kmp_str_buf_t * buffer -) { - - struct kmp_i18n_id_range_t { - kmp_i18n_id_t first; - kmp_i18n_id_t last; - }; // struct kmp_i18n_id_range_t - - static struct kmp_i18n_id_range_t ranges[] = { - { kmp_i18n_prp_first, kmp_i18n_prp_last }, - { kmp_i18n_str_first, kmp_i18n_str_last }, - { kmp_i18n_fmt_first, kmp_i18n_fmt_last }, - { kmp_i18n_msg_first, kmp_i18n_msg_last }, - { kmp_i18n_hnt_first, kmp_i18n_hnt_last } - }; // ranges - - int num_of_ranges = sizeof( ranges ) / sizeof( struct kmp_i18n_id_range_t ); - int range; - kmp_i18n_id_t id; - - for ( range = 0; range < num_of_ranges; ++ range ) { - __kmp_str_buf_print( buffer, "*** Set #%d ***\n", range + 1 ); - for ( id = (kmp_i18n_id_t)( ranges[ range ].first + 1 ); - id < ranges[ range ].last; - id = (kmp_i18n_id_t)( id + 1 ) ) { - __kmp_str_buf_print( buffer, "%d: <<%s>>\n", id, __kmp_i18n_catgets( id ) ); - }; // for id - }; // for range - - __kmp_printf( "%s", buffer->str ); + va_start(args, id_arg); -} // __kmp_i18n_dump_catalog + // We use unsigned for the ID argument and explicitly cast it here to the + // right enumerator because variadic functions are not compatible with + // default promotions. + kmp_i18n_id_t id = (kmp_i18n_id_t)id_arg; -// ------------------------------------------------------------------------------------------------- - -kmp_msg_t -__kmp_msg_format( - unsigned id_arg, - ... -) { - - kmp_msg_t msg; - va_list args; - kmp_str_buf_t buffer; - __kmp_str_buf_init( & buffer ); - - va_start( args, id_arg ); - - // We use unsigned for the ID argument and explicitly cast it here to the - // right enumerator because variadic functions are not compatible with - // default promotions. - kmp_i18n_id_t id = (kmp_i18n_id_t)id_arg; - - #if KMP_OS_UNIX - // On Linux* OS and OS X*, printf() family functions process parameter numbers, for example: - // "%2$s %1$s". - __kmp_str_buf_vprint( & buffer, __kmp_i18n_catgets( id ), args ); - #elif KMP_OS_WINDOWS - // On Winodws, printf() family functions does not recognize GNU style parameter numbers, - // so we have to use FormatMessage() instead. It recognizes parameter numbers, e. g.: - // "%2!s! "%1!s!". - { - LPTSTR str = NULL; - int len; - FormatMessage( - FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, - __kmp_i18n_catgets( id ), - 0, 0, - (LPTSTR)( & str ), - 0, - & args - ); - len = ___strip_crs( str ); - __kmp_str_buf_cat( & buffer, str, len ); - LocalFree( str ); - } - #else - #error - #endif - va_end( args ); - __kmp_str_buf_detach( & buffer ); - - msg.type = (kmp_msg_type_t)( id >> 16 ); - msg.num = id & 0xFFFF; - msg.str = buffer.str; - msg.len = buffer.used; - - return msg; +#if KMP_OS_UNIX + // On Linux* OS and OS X*, printf() family functions process parameter + // numbers, for example: "%2$s %1$s". + __kmp_str_buf_vprint(&buffer, __kmp_i18n_catgets(id), args); +#elif KMP_OS_WINDOWS + // On Winodws, printf() family functions does not recognize GNU style + // parameter numbers, so we have to use FormatMessage() instead. It recognizes + // parameter numbers, e. g.: "%2!s! "%1!s!". + { + LPTSTR str = NULL; + int len; + FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + __kmp_i18n_catgets(id), 0, 0, (LPTSTR)(&str), 0, &args); + len = ___strip_crs(str); + __kmp_str_buf_cat(&buffer, str, len); + LocalFree(str); + } +#else +#error +#endif + va_end(args); + __kmp_str_buf_detach(&buffer); + + msg.type = (kmp_msg_type_t)(id >> 16); + msg.num = id & 0xFFFF; + msg.str = buffer.str; + msg.len = buffer.used; + + return msg; } // __kmp_msg_format -// ------------------------------------------------------------------------------------------------- - -static -char * -sys_error( - int err -) { - - char * message = NULL; - - #if KMP_OS_WINDOWS - - LPVOID buffer = NULL; - int len; - DWORD rc; - rc = - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - err, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language. - (LPTSTR) & buffer, - 0, - NULL - ); - if ( rc > 0 ) { - // Message formatted. Copy it (so we can free it later with normal free(). - message = __kmp_str_format( "%s", (char *) buffer ); - len = ___strip_crs( message ); // Delete carriage returns if any. - // Strip trailing newlines. - while ( len > 0 && message[ len - 1 ] == '\n' ) { - -- len; - }; // while - message[ len ] = 0; - } else { - // FormatMessage() failed to format system error message. GetLastError() would give us - // error code, which we would convert to message... this it dangerous recursion, which - // cannot clarify original error, so we will not even start it. - }; // if - if ( buffer != NULL ) { - LocalFree( buffer ); - }; // if +// ----------------------------------------------------------------------------- +static char *sys_error(int err) { - #else // Non-Windows* OS: Linux* OS or OS X* - - /* - There are 2 incompatible versions of strerror_r: - - char * strerror_r( int, char *, size_t ); // GNU version - int strerror_r( int, char *, size_t ); // XSI version - */ - - #if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \ - (defined(__BIONIC__) && defined(_GNU_SOURCE) && \ - __ANDROID_API__ >= __ANDROID_API_M__) - - // GNU version of strerror_r. - - char buffer[ 2048 ]; - char * const err_msg = strerror_r( err, buffer, sizeof( buffer ) ); - // Do not eliminate this assignment to temporary variable, otherwise compiler would - // not issue warning if strerror_r() returns `int' instead of expected `char *'. - message = __kmp_str_format( "%s", err_msg ); - - #else // OS X*, FreeBSD* etc. - - // XSI version of strerror_r. - - int size = 2048; - char * buffer = (char *) KMP_INTERNAL_MALLOC( size ); - int rc; - if (buffer == NULL) { - KMP_FATAL(MemoryAllocFailed); - } - rc = strerror_r( err, buffer, size ); - if ( rc == -1 ) { - rc = errno; // XSI version sets errno. - }; // if - while ( rc == ERANGE ) { // ERANGE means the buffer is too small. - KMP_INTERNAL_FREE( buffer ); - size *= 2; - buffer = (char *) KMP_INTERNAL_MALLOC( size ); - if (buffer == NULL) { - KMP_FATAL(MemoryAllocFailed); - } - rc = strerror_r( err, buffer, size ); - if ( rc == -1 ) { - rc = errno; // XSI version sets errno. - }; // if - }; // while - if ( rc == 0 ) { - message = buffer; - } else { - // Buffer is unused. Free it. - KMP_INTERNAL_FREE( buffer ); - }; // if - - #endif - - #endif /* KMP_OS_WINDOWS */ - - if ( message == NULL ) { - // TODO: I18n this message. - message = __kmp_str_format( "%s", "(No system error message available)" ); - }; // if - return message; + char *message = NULL; -} // sys_error +#if KMP_OS_WINDOWS + + LPVOID buffer = NULL; + int len; + DWORD rc; + rc = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language. + (LPTSTR)&buffer, 0, NULL); + if (rc > 0) { + // Message formatted. Copy it (so we can free it later with normal free(). + message = __kmp_str_format("%s", (char *)buffer); + len = ___strip_crs(message); // Delete carriage returns if any. + // Strip trailing newlines. + while (len > 0 && message[len - 1] == '\n') { + --len; + }; // while + message[len] = 0; + } else { + // FormatMessage() failed to format system error message. GetLastError() + // would give us error code, which we would convert to message... this it + // dangerous recursion, which cannot clarify original error, so we will not + // even start it. + }; // if + if (buffer != NULL) { + LocalFree(buffer); + }; // if + +#else // Non-Windows* OS: Linux* OS or OS X* + +/* There are 2 incompatible versions of strerror_r: + + char * strerror_r( int, char *, size_t ); // GNU version + int strerror_r( int, char *, size_t ); // XSI version +*/ -// ------------------------------------------------------------------------------------------------- +#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \ + (defined(__BIONIC__) && defined(_GNU_SOURCE) && \ + __ANDROID_API__ >= __ANDROID_API_M__) + // GNU version of strerror_r. + + char buffer[2048]; + char *const err_msg = strerror_r(err, buffer, sizeof(buffer)); + // Do not eliminate this assignment to temporary variable, otherwise compiler + // would not issue warning if strerror_r() returns `int' instead of expected + // `char *'. + message = __kmp_str_format("%s", err_msg); + +#else // OS X*, FreeBSD* etc. + // XSI version of strerror_r. + int size = 2048; + char *buffer = (char *)KMP_INTERNAL_MALLOC(size); + int rc; + if (buffer == NULL) { + KMP_FATAL(MemoryAllocFailed); + } + rc = strerror_r(err, buffer, size); + if (rc == -1) { + rc = errno; // XSI version sets errno. + }; // if + while (rc == ERANGE) { // ERANGE means the buffer is too small. + KMP_INTERNAL_FREE(buffer); + size *= 2; + buffer = (char *)KMP_INTERNAL_MALLOC(size); + if (buffer == NULL) { + KMP_FATAL(MemoryAllocFailed); + } + rc = strerror_r(err, buffer, size); + if (rc == -1) { + rc = errno; // XSI version sets errno. + }; // if + }; // while + if (rc == 0) { + message = buffer; + } else { // Buffer is unused. Free it. + KMP_INTERNAL_FREE(buffer); + }; // if + +#endif + +#endif /* KMP_OS_WINDOWS */ + + if (message == NULL) { + // TODO: I18n this message. + message = __kmp_str_format("%s", "(No system error message available)"); + }; // if + return message; +} // sys_error -kmp_msg_t -__kmp_msg_error_code( - int code -) { +// ----------------------------------------------------------------------------- +kmp_msg_t __kmp_msg_error_code(int code) { - kmp_msg_t msg; - msg.type = kmp_mt_syserr; - msg.num = code; - msg.str = sys_error( code ); - msg.len = KMP_STRLEN( msg.str ); - return msg; + kmp_msg_t msg; + msg.type = kmp_mt_syserr; + msg.num = code; + msg.str = sys_error(code); + msg.len = KMP_STRLEN(msg.str); + return msg; } // __kmp_msg_error_code -// ------------------------------------------------------------------------------------------------- - -kmp_msg_t -__kmp_msg_error_mesg( - char const * mesg -) { +// ----------------------------------------------------------------------------- +kmp_msg_t __kmp_msg_error_mesg(char const *mesg) { - kmp_msg_t msg; - msg.type = kmp_mt_syserr; - msg.num = 0; - msg.str = __kmp_str_format( "%s", mesg ); - msg.len = KMP_STRLEN( msg.str ); - return msg; + kmp_msg_t msg; + msg.type = kmp_mt_syserr; + msg.num = 0; + msg.str = __kmp_str_format("%s", mesg); + msg.len = KMP_STRLEN(msg.str); + return msg; } // __kmp_msg_error_mesg -// ------------------------------------------------------------------------------------------------- - -void -__kmp_msg( - kmp_msg_severity_t severity, - kmp_msg_t message, - ... -) { - - va_list args; - kmp_i18n_id_t format; // format identifier - kmp_msg_t fmsg; // formatted message - kmp_str_buf_t buffer; - - if ( severity != kmp_ms_fatal && __kmp_generate_warnings == kmp_warnings_off ) - return; // no reason to form a string in order to not print it - - __kmp_str_buf_init( & buffer ); - - // Format the primary message. - switch ( severity ) { - case kmp_ms_inform : { - format = kmp_i18n_fmt_Info; - } break; - case kmp_ms_warning : { - format = kmp_i18n_fmt_Warning; - } break; - case kmp_ms_fatal : { - format = kmp_i18n_fmt_Fatal; - } break; - default : { - KMP_DEBUG_ASSERT( 0 ); - }; +// ----------------------------------------------------------------------------- +void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...) { + + va_list args; + kmp_i18n_id_t format; // format identifier + kmp_msg_t fmsg; // formatted message + kmp_str_buf_t buffer; + + if (severity != kmp_ms_fatal && __kmp_generate_warnings == kmp_warnings_off) + return; // no reason to form a string in order to not print it + + __kmp_str_buf_init(&buffer); + + // Format the primary message. + switch (severity) { + case kmp_ms_inform: { + format = kmp_i18n_fmt_Info; + } break; + case kmp_ms_warning: { + format = kmp_i18n_fmt_Warning; + } break; + case kmp_ms_fatal: { + format = kmp_i18n_fmt_Fatal; + } break; + default: { KMP_DEBUG_ASSERT(0); }; + }; // switch + fmsg = __kmp_msg_format(format, message.num, message.str); + __kmp_str_free(&message.str); + __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len); + __kmp_str_free(&fmsg.str); + + // Format other messages. + va_start(args, message); + for (;;) { + message = va_arg(args, kmp_msg_t); + if (message.type == kmp_mt_dummy && message.str == NULL) { + break; + }; // if + if (message.type == kmp_mt_dummy && message.str == __kmp_msg_empty.str) { + continue; + }; // if + switch (message.type) { + case kmp_mt_hint: { + format = kmp_i18n_fmt_Hint; + } break; + case kmp_mt_syserr: { + format = kmp_i18n_fmt_SysErr; + } break; + default: { KMP_DEBUG_ASSERT(0); }; }; // switch - fmsg = __kmp_msg_format( format, message.num, message.str ); + fmsg = __kmp_msg_format(format, message.num, message.str); __kmp_str_free(&message.str); - __kmp_str_buf_cat( & buffer, fmsg.str, fmsg.len ); + __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len); __kmp_str_free(&fmsg.str); + }; // forever + va_end(args); - // Format other messages. - va_start( args, message ); - for ( ; ; ) { - message = va_arg( args, kmp_msg_t ); - if ( message.type == kmp_mt_dummy && message.str == NULL ) { - break; - }; // if - if ( message.type == kmp_mt_dummy && message.str == __kmp_msg_empty.str ) { - continue; - }; // if - switch ( message.type ) { - case kmp_mt_hint : { - format = kmp_i18n_fmt_Hint; - } break; - case kmp_mt_syserr : { - format = kmp_i18n_fmt_SysErr; - } break; - default : { - KMP_DEBUG_ASSERT( 0 ); - }; - }; // switch - fmsg = __kmp_msg_format( format, message.num, message.str ); - __kmp_str_free(&message.str); - __kmp_str_buf_cat( & buffer, fmsg.str, fmsg.len ); - __kmp_str_free(&fmsg.str); - }; // forever - va_end( args ); - - // Print formatted messages. - // This lock prevents multiple fatal errors on the same problem. - // __kmp_acquire_bootstrap_lock( & lock ); // GEH - This lock causing tests to hang on OS X*. - __kmp_printf( "%s", buffer.str ); - __kmp_str_buf_free( & buffer ); - - if ( severity == kmp_ms_fatal ) { - #if KMP_OS_WINDOWS - __kmp_thread_sleep( 500 ); /* Delay to give message a chance to appear before reaping */ - #endif - __kmp_abort_process(); - }; // if + // Print formatted messages. + // This lock prevents multiple fatal errors on the same problem. + // __kmp_acquire_bootstrap_lock( & lock ); // GEH - This lock causing tests + // to hang on OS X*. + __kmp_printf("%s", buffer.str); + __kmp_str_buf_free(&buffer); - // __kmp_release_bootstrap_lock( & lock ); // GEH - this lock causing tests to hang on OS X*. + if (severity == kmp_ms_fatal) { +#if KMP_OS_WINDOWS + __kmp_thread_sleep( + 500); /* Delay to give message a chance to appear before reaping */ +#endif + __kmp_abort_process(); + }; // if -} // __kmp_msg + // __kmp_release_bootstrap_lock( & lock ); // GEH - this lock causing tests + // to hang on OS X*. -// ------------------------------------------------------------------------------------------------- +} // __kmp_msg // end of file // |