1 /* Expression evaluation for plural form selection.
2 Copyright (C) 2000-2003, 2005, 2019-2020 Free Software Foundation, Inc.
3 Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 /* Specification. */
23 #include "plural-eval.h"
24
25 #include <stddef.h>
26 #include <signal.h>
27
28 #include "plural-exp.h"
29
30
31 #define STATIC /*extern*/
32
33 /* Include the expression evaluation code from libintl, this time with
34 'extern' linkage. */
35 #include "eval-plural.h"
36
37
38 /* Exit point. Must be set before calling install_sigfpe_handler(). */
39 sigjmp_buf sigfpe_exit;
40
41 #if USE_SIGINFO
42
43 /* Additional information that is set before sigfpe_exit is invoked. */
44 int volatile sigfpe_code;
45
46 /* Signal handler called in case of arithmetic exception (e.g. division
47 by zero) during plural_eval. */
48 static _GL_ASYNC_SAFE void
sigfpe_handler(int sig,siginfo_t * sip,void * scp)49 sigfpe_handler (int sig, siginfo_t *sip, void *scp)
50 {
51 sigfpe_code = sip->si_code;
52 /* This handler is invoked on the thread that caused the SIGFPE, that is,
53 the thread that is doing plural evaluation. Therefore it's OK to use
54 siglongjmp. */
55 siglongjmp (sigfpe_exit, 1);
56 }
57
58 #else
59
60 /* Signal handler called in case of arithmetic exception (e.g. division
61 by zero) during plural_eval. */
62 static _GL_ASYNC_SAFE void
sigfpe_handler(int sig)63 sigfpe_handler (int sig)
64 {
65 /* This handler is invoked on the thread that caused the SIGFPE, that is,
66 the thread that is doing plural evaluation. Therefore it's OK to use
67 siglongjmp. */
68 siglongjmp (sigfpe_exit, 1);
69 }
70
71 #endif
72
73 void
install_sigfpe_handler(void)74 install_sigfpe_handler (void)
75 {
76 #if USE_SIGINFO
77 struct sigaction action;
78 action.sa_sigaction = sigfpe_handler;
79 action.sa_flags = SA_SIGINFO;
80 sigemptyset (&action.sa_mask);
81 sigaction (SIGFPE, &action, (struct sigaction *) NULL);
82 #else
83 signal (SIGFPE, sigfpe_handler);
84 #endif
85 }
86
87 void
uninstall_sigfpe_handler(void)88 uninstall_sigfpe_handler (void)
89 {
90 #if USE_SIGINFO
91 struct sigaction action;
92 action.sa_handler = SIG_DFL;
93 action.sa_flags = 0;
94 sigemptyset (&action.sa_mask);
95 sigaction (SIGFPE, &action, (struct sigaction *) NULL);
96 #else
97 signal (SIGFPE, SIG_DFL);
98 #endif
99 }
100