Example #1
0
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
Example #2
0
static inline void *allocate(size_t size) {
  void *ptr = KMP_INTERNAL_MALLOC(size);
  if (ptr == NULL) {
    KMP_FATAL(MemoryAllocFailed);
  }
  return ptr;
} // allocate
Example #3
0
char *
__kmp_str_format(           // Allocated string.
    char const * format,    // Format string.
    ...                     // Other parameters.
) {

    va_list args;
    int     size   = 512;
    char *  buffer = NULL;
    int     rc;

    // Allocate buffer.
    buffer = (char *) KMP_INTERNAL_MALLOC( size );
    if ( buffer == NULL ) {
	KMP_FATAL( MemoryAllocFailed );
    }; // if

    for ( ; ; ) {

        // Try to format string.
        va_start( args, format );
        rc = vsnprintf( buffer, size, format, args );
        va_end( args );

        // No errors, string has been formatted.
        if ( rc >= 0 && rc < size ) {
            break;
        }; // if

        // Error occured, buffer is too small.
        if ( rc >= 0 ) {
            // C99-conforming implementation of vsnprintf returns required buffer size.
            size = rc + 1;
        } else {
            // Older implementations just return -1.
            size = size * 2;
        }; // if

        // Enlarge buffer and try again.
        buffer = (char *) KMP_INTERNAL_REALLOC( buffer, size );
        if ( buffer == NULL ) {
    	    KMP_FATAL( MemoryAllocFailed );
        }; // if

    }; // forever

    return buffer;

} // func __kmp_str_format
Example #4
0
void
__kmp_str_buf_detach(
    kmp_str_buf_t *  buffer
) {

    KMP_STR_BUF_INVARIANT( buffer );

    // If internal bulk is used, allocate memory and copy it.
    if ( buffer->size <= sizeof( buffer->bulk ) ) {
        buffer->str = (char *) KMP_INTERNAL_MALLOC( buffer->size );
        if ( buffer->str == NULL ) {
		KMP_FATAL( MemoryAllocFailed );
        }; // if
        memcpy( buffer->str, buffer->bulk, buffer->used + 1 );
    }; // if

} // __kmp_str_buf_detach
Example #5
0
void
__kmp_str_buf_reserve(
    kmp_str_buf_t * buffer,
    int             size
) {

    KMP_STR_BUF_INVARIANT( buffer );
    KMP_DEBUG_ASSERT( size >= 0 );

    if ( buffer->size < size ) {

        // Calculate buffer size.
        do {
            buffer->size *= 2;
        } while ( buffer->size < size );

        // Enlarge buffer.
        if ( buffer->str == & buffer->bulk[ 0 ] ) {
            buffer->str = (char *) KMP_INTERNAL_MALLOC( buffer->size );
            if ( buffer->str == NULL ) {
		KMP_FATAL( MemoryAllocFailed );
            }; // if
            memcpy( buffer->str, buffer->bulk, buffer->used + 1 );
        } else {
            buffer->str = (char *) KMP_INTERNAL_REALLOC( buffer->str, buffer->size );
            if ( buffer->str == NULL ) {
		KMP_FATAL( MemoryAllocFailed );
            }; // if
        }; // if

    }; // if

    KMP_DEBUG_ASSERT( buffer->size > 0 );
    KMP_DEBUG_ASSERT( buffer->size >= size );
    KMP_STR_BUF_INVARIANT( buffer );

} // __kmp_str_buf_reserve
Example #6
0
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
Example #7
0
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