Math Processor Unit Library

libmpu – library of arithmetic functions for integer, real, and complex numbers of increased digit capacity

16 Commits   0 Branches   2 Tags

/***************************************************************
  __MPU_STRERROR.C

       This file contains source code of functions for
       getting MATH ERROR messages.

       PART OF : MPU - library .

       USAGE   : Internal only .

       NOTE    : NONE .

       Copyright (C) 2000 - 2024  by Andrew V.Kosteltsev.
       All Rights Reserved.
 ***************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <nls.h>

#include <errno.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>

#include <libmpu.h>
#include <mpu-context.h>
#include <mpu-symbols.h>

#include <mpu-math-errno.h>
#include <mpu-mtherr.h>

#include <mpu-real.h>


#define MPU_MATH_EUNKNOWN_MSG  "Unknown MPU error"

/***************************************************************
  __mpu_utf8mpu_error()

     Возврашает указатель на строку, содержащую текстовый
     эквивалент ошибок MPU( Math Processor Unit ), имеющих
     код ERRNUM.

     Параметр WHO определяет источник ошибки и может иметь
     одно из, определенных в __tx_math_errno.h, значений:
        #define _COMPLEX_   3
        #define _REAL_      2
        #define _INTEGER_   1
        #define _MATH_      0
     .

     Возвращаемое значение переводится в кодировку UTF-8,
     согласно локали ru.

     В случае ошибки возвращает RET == (__mpu_utf8_t *)NULL.
     NOTE:
     ====
        Функция выделяет память под возвращаемый указатель.
        Ответственность за освобождение данной памяти лежит
        на ползователе.
 ***************************************************************/
__mpu_utf8_t *
__mpu_utf8mpu_error( int who, __mpu_error_t errnum )
{
  __mpu_utf8_t *e   = NULL;
  __mpu_utf8_t *ret = NULL;

  switch( who )
  {
     case _COMPLEX_:
        e = (__mpu_utf8_t *)__MPU_COMPLEX_ERR_MSG( errnum );
        break;
     case _REAL_   :
        e = (__mpu_utf8_t *)__MPU_REAL_ERR_MSG( errnum );
        break;
     case _INTEGER_:
        e = (__mpu_utf8_t *)__MPU_INTEGER_ERR_MSG( errnum );
        break;
     case _MATH_   :
        e = (__mpu_utf8_t *)__MPU_MATH_ERR_MSG( errnum );
        break;
  }
  if( e == (__mpu_utf8_t *)0 )
  {
     /****************************************************
       NOTE:
          MPU_MATH_ERROR_MSG_SIZE определено в
          LIBMPU.H ( == 4096).
      ****************************************************/
     static __mpu_utf8_t unknow_error[MPU_MATH_ERROR_MSG_SIZE];
     static __mpu_utf8_t   code_error[64];

     strncpy( unknow_error, (__mpu_utf8_t *)MPU_MATH_EUNKNOWN_MSG, (size_t)(MPU_MATH_ERROR_MSG_SIZE-1) );
     unknow_error[MPU_MATH_ERROR_MSG_SIZE-1] = '\0';
     snprintf( code_error, (size_t)64, ": #%d", errnum );
     strncat( unknow_error, code_error, (size_t)(MPU_MATH_ERROR_MSG_SIZE-1) );
     unknow_error[MPU_MATH_ERROR_MSG_SIZE-1] = '\0';

     e = unknow_error;
  }

  /* а вот теперь можно применить gettext: */
  /* ====================================  */
  {
#if ENABLE_NLS == 1
    char   *back_locale = NULL;
    char   *lt          = NULL;
    char   *back_env    = NULL;
#endif
    size_t  len = 0;

#if ENABLE_NLS == 1
    /*******************************************************
      Так как gettext в первую очередь проверяет LC_ALL,
      затем LC_MESSAGE и в процессе работы пользуется
      LC_CTYPE, мы для простоты временно выставляем LC_ALL.
      Использование LC_MESSAGE при отличном от него LC_ALL
      нам ничего не даст.
     *******************************************************/
    back_locale = setlocale( LC_ALL, (const char *)NULL );
    lt = setlocale( LC_ALL, (const char *)"ru" );

    back_env = getenv( (const char *)"LANGUAGE" );
    (void)setenv( (const char *)"LANGUAGE", (const char *)"ru", 1 /* 1 - overwrite */ );

    e = (__mpu_utf8_t *)dgettext( PACKAGE, (const char *)e );
#endif

    len = strlen( e );
    ret = (__mpu_utf8_t *)malloc( (len + 1) * sizeof( __mpu_utf8_t ) );
    if( !ret )
    {
#if ENABLE_NLS == 1
      /* restore locale and environment */
      if( back_locale )
        (void)setlocale( LC_ALL, (const char *)back_locale );

      if( back_env )
        (void)setenv( (const char *)"LANGUAGE", (const char *)back_env, 1 /* 1 - overwrite */ );
#endif

      return( (__mpu_utf8_t *)NULL );
    }

    strncpy( ret, e, len+1 );

#if ENABLE_NLS == 1
    /* restore locale and environment */
    if( back_locale )
      (void)setlocale( LC_ALL, (const char *)back_locale );

    if( back_env )
      (void)setenv( (const char *)"LANGUAGE", (const char *)back_env, 1 /* 1 - overwrite */ );
#endif
  }

  return( ret );

} /* End of __mpu_utf8mpu_error() */