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