(root)/
gettext-0.22.4/
gettext-tools/
src/
plural-eval.c
       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
      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
      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
      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
      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  }