/***************************************************************
__MPU_WARNING.C
This file contains source code of functions for
MPU extra warnings operations.
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> /* errno(3) */
#include <string.h> /* strcpy(3) */
#include <strings.h> /* bzero(3) */
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#include <libmpu.h>
#include <mpu-context.h>
#include <mpu-emutype.h>
#include <mpu-integer.h>
#include <mpu-real.h>
#include <mpu-floatp.h>
#include <mpu-ioreal.h>
#include <mpu-char.h>
#include <mpu-symbols.h>
#include <mpu-math-errno.h>
#include <mpu-mtherr.h>
/*
__mpu_warning() работает с внешним форматом чисел.
Данная вункция вызывается только в том случае,
когда переменная __extra_warnings имеет значение
отличное от нуля.
Пользователь может определить собственную функцию
__mpu_warning() в качестве замены данного стандартного
обработчика вывода дополнительных предупреждений.
*/
#define MSG_FORMAT "message: %0.4d: %s(): %s" /* type, name, msg */
#define ERROR_MSG_FORMAT "error: E%0.4d: %s(): %s" /* type, name, msg */
#define WARNING_MSG_FORMAT "warning: W%0.4d: %s(): %s" /* type, name, msg */
int __use_default_mpu_warning = 1;
void __mpu_warning( struct __exception *pexcept )
{
__mpu_char8_t str[MPU_MATH_ERROR_MSG_SIZE];
__mpu_char8_t error_msg_format[MPU_MATH_ERROR_MSG_SIZE];
__mpu_char8_t warning_msg_format[MPU_MATH_ERROR_MSG_SIZE];
__mpu_char8_t fmt[MPU_MATH_ERROR_MSG_SIZE];
/************************************************************
Floating point exception.
==========================================================
Исключение операции с плавающей точкой.
************************************************************/
__mpu_char8_t *exception = (__mpu_char8_t *)N_("Floating point exception");
/************************************************************
Unknown message source.
==========================================================
Неизвестный источник сообщения.
************************************************************/
__mpu_char8_t *unknown = (__mpu_char8_t *)N_("Unknown message source");
#if ENABLE_NLS == 1
char *back_locale = NULL;
char *lt = NULL;
char *back_env = NULL;
/*******************************************************
Так как 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 */ );
exception = (__mpu_char8_t *)dgettext( PACKAGE, (const char *)exception );
unknown = (__mpu_char8_t *)dgettext( PACKAGE, (const char *)unknown );
#endif
strcpy( (char *)&error_msg_format[0], ERROR_MSG_FORMAT );
strcpy( (char *)&warning_msg_format[0], WARNING_MSG_FORMAT );
/*******************************************************
ERRNO FOR MESSAGES:
_INTEGER_ + 1000, _REAL_ + 2000, _COMPLEX_ + 3000.
MESSAGES TYPE:
TRUE - error; FALSE - warning.
*******************************************************/
switch( pexcept->who )
{
case _INTEGER_:
pexcept->type = __integer_error_no;
sprintf( (char *)&str[0],
(pexcept->msg_type) ? (error_msg_format) :
(warning_msg_format),
pexcept->type + 1000, (char *)pexcept->name, (char *)pexcept->msg );
break;
case _REAL_:
pexcept->type = __real_error_no;
sprintf( (char *)&str[0],
(pexcept->msg_type) ? (error_msg_format) :
(warning_msg_format),
pexcept->type + 2000, (char *)pexcept->name, (char *)pexcept->msg );
break;
case _COMPLEX_:
pexcept->type = __complex_error_no;
sprintf( (char *)&str[0],
(pexcept->msg_type) ? (error_msg_format) :
(warning_msg_format),
pexcept->type + 3000, (char *)pexcept->name, (char *)pexcept->msg );
break;
case _MATH_:
{
__mpu_char8_t s[REAL_131072_MAX_STRING]; /* mpu-floatp.h */
__mpu_char8_t num[REAL_131072_MAX_STRING];
__mpu_char8_t st[MPU_MATH_ERROR_MSG_SIZE];
EMUSHORT eic[NPIR_131072];
int n_bits;
/* Type the string STR[] */
if( pexcept->arg_1 )
{
n_bits = pexcept->nb_a1 * BITS_PER_BYTE;
unpack( (EMUSHORT *)&eic[0], (EMUSHORT *)pexcept->arg_1, n_bits );
ei_real_to_ascii( (__mpu_char8_t *)&s[0],
(EMUSHORT *)&eic[0],
(_get_ndec( pexcept->nb_a1 ) < 12) ? _get_ndec( pexcept->nb_a1 ): 12,
'E', 0, 0, n_bits );
strcpy( (char *)&num[0], (char *)&s[0] );
strcpy( (char *)&fmt[0], exception );
strcat( (char *)&fmt[0], ": %s( %s" );
sprintf( (char *)&str[0], (const char *)&fmt[0], (char *)pexcept->name, (char *)&num[0] );
}
else
{
strcpy( (char *)&fmt[0], exception );
strcat( (char *)&fmt[0], ": %s( " );
sprintf( (char *)&str[0], (const char *)&fmt[0], (char *)pexcept->name );
}
if( pexcept->arg_2 )
{
n_bits = pexcept->nb_a2 * BITS_PER_BYTE;
unpack( (EMUSHORT *)&eic[0], (EMUSHORT *)pexcept->arg_2, n_bits );
ei_real_to_ascii( (__mpu_char8_t *)&s[0],
(EMUSHORT *)&eic[0],
(_get_ndec( pexcept->nb_a2 ) < 12) ? _get_ndec( pexcept->nb_a2 ): 12,
'E', 0, 0, n_bits );
strcpy( (char *)&num[0], (char *)&s[0] );
strcpy( (char *)&fmt[0], ", %s ): %s" );
sprintf( (char *)&st[0], (const char *)&fmt[0], (char *)&num[0], (char *)pexcept->msg );
strcat( (char *)&str[0], (char *)&st[0] );
}
else
{
strcpy( (char *)&fmt[0], " ): %s" );
sprintf( (char *)&st[0], (const char *)&fmt[0], (char *)pexcept->msg );
strcat( (char *)&str[0], (char *)&st[0] );
}
}
break;
default:
{
strcpy( (char *)&fmt[0], unknown );
strcat( (char *)&fmt[0], ": %0.4d: %s(): %s" );
sprintf( (char *)&str[0], (const char *)&fmt[0], pexcept->type, (char *)pexcept->name, (char *)pexcept->msg );
}
break;
} /* End switch( pexcept->who ) */
strcpy( (char *)&fmt[0], "%s.\n" );
fprintf( stderr, (const char *)&fmt[0], (char *)&str[0] );
#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;
} /* End of __mpu_warning() */