summaryrefslogtreecommitdiff
path: root/mpu/mpu-warning.c
blob: 60c314e80eb2e74a372de07cfc3146c80f14ccd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/***************************************************************
  __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() */