void __kmp_error_construct2( kmp_i18n_id_t id, // Message identifier. enum cons_type ct, // First construct type. ident_t const * ident, // First construct ident. struct cons_data const * cons // Second construct. ) { char const * construct1 = __kmp_pragma( ct, ident ); char const * construct2 = __kmp_pragma( cons->type, cons->ident ); __kmp_msg( kmp_ms_fatal, __kmp_msg_format( id, construct1, construct2 ), __kmp_msg_null ); KMP_INTERNAL_FREE( (void *) construct1 ); KMP_INTERNAL_FREE( (void *) construct2 ); }
void __kmp_env_blk_free( kmp_env_blk_t * block // M: Block of environment variables to free. ) { KMP_INTERNAL_FREE( (void *) block->vars ); KMP_INTERNAL_FREE( (void *) block->bulk ); block->count = 0; block->vars = NULL; block->bulk = NULL; } // __kmp_env_blk_free
void __kmp_str_free( char const * * str ) { KMP_DEBUG_ASSERT( str != NULL ); KMP_INTERNAL_FREE( (void *) * str ); * str = NULL; } // func __kmp_str_free
void __kmp_env_free( char const * * value ) { KMP_DEBUG_ASSERT( value != NULL ); KMP_INTERNAL_FREE( (void *) * value ); * value = NULL; } // func __kmp_env_free
char *__kmp_env_get(char const *name) { char *result = NULL; #if KMP_OS_UNIX char const *value = getenv(name); if (value != NULL) { size_t len = KMP_STRLEN(value) + 1; result = (char *)KMP_INTERNAL_MALLOC(len); if (result == NULL) { KMP_FATAL(MemoryAllocFailed); } KMP_STRNCPY_S(result, len, value, len); } #elif KMP_OS_WINDOWS /* We use GetEnvironmentVariable for Windows* OS instead of getenv because the act of loading a DLL on Windows* OS makes any user-set environment variables (i.e. with putenv()) unavailable. getenv() apparently gets a clean copy of the env variables as they existed at the start of the run. JH 12/23/2002 */ DWORD rc; rc = GetEnvironmentVariable(name, NULL, 0); if (!rc) { DWORD error = GetLastError(); if (error != ERROR_ENVVAR_NOT_FOUND) { __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null); } // Variable is not found, it's ok, just continue. } else { DWORD len = rc; result = (char *)KMP_INTERNAL_MALLOC(len); if (result == NULL) { KMP_FATAL(MemoryAllocFailed); } rc = GetEnvironmentVariable(name, result, len); if (!rc) { // GetEnvironmentVariable() may return 0 if variable is empty. // In such a case GetLastError() returns ERROR_SUCCESS. DWORD error = GetLastError(); if (error != ERROR_SUCCESS) { // Unexpected error. The variable should be in the environment, // and buffer should be large enough. __kmp_fatal(KMP_MSG(CantGetEnvVar, name), KMP_ERR(error), __kmp_msg_null); KMP_INTERNAL_FREE((void *)result); result = NULL; } } } #else #error Unknown or unsupported OS. #endif return result; } // func __kmp_env_get
void __kmp_error_construct( kmp_i18n_id_t id, // Message identifier. enum cons_type ct, // Construct type. ident_t const * ident // Construct ident. ) { char const * construct = __kmp_pragma( ct, ident ); __kmp_msg( kmp_ms_fatal, __kmp_msg_format( id, construct ), __kmp_msg_null ); KMP_INTERNAL_FREE( (void *) construct ); }
void __kmp_str_loc_free( kmp_str_loc_t * loc ) { __kmp_str_fname_free( & loc->fname ); KMP_INTERNAL_FREE( loc->_bulk ); loc->_bulk = NULL; loc->file = NULL; loc->func = NULL; } // kmp_str_loc_free
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_i8n_table_free
void __kmp_str_buf_free( kmp_str_buf_t * buffer ) { KMP_STR_BUF_INVARIANT( buffer ); if ( buffer->size > sizeof( buffer->bulk ) ) { KMP_INTERNAL_FREE( buffer->str ); }; // if buffer->str = buffer->bulk; buffer->size = sizeof( buffer->bulk ); buffer->used = 0; KMP_STR_BUF_INVARIANT( buffer ); } // __kmp_str_buf_free
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 }; // if KMP_INTERNAL_FREE( (void *) value ); return cp; } // func get_code_page
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_INTERNAL_FREE( (void *) message.str ); __kmp_str_buf_cat( & buffer, fmsg.str, fmsg.len ); KMP_INTERNAL_FREE( (void *) 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 ); KMP_INTERNAL_FREE( (void *) message.str ); __kmp_str_buf_cat( & buffer, fmsg.str, fmsg.len ); KMP_INTERNAL_FREE( (void *) 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 // __kmp_release_bootstrap_lock( & lock ); // GEH - this lock causing tests to hang on OS X*. } // __kmp_msg
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 #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) // 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; // TODO: Add checking result of malloc(). 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
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 // 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; } // ___catgets
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( kmp_ms_warning, KMP_MSG( CantOpenMessageCatalog, name ), KMP_ERR( error ), KMP_HNT( CheckEnvVar, "NLSPATH", nlspath ), KMP_HNT( CheckEnvVar, "LANG", lang ), __kmp_msg_null ); 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 ); }; // if } // func __kmp_i18n_do_catopen