Blame intl/plural-exp.c

Packit 6c4009
/* Expression parsing for plural form selection.
Packit 6c4009
   Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit 6c4009
   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
Packit 6c4009
Packit 6c4009
   This program is free software: you can redistribute it and/or modify
Packit 6c4009
   it under the terms of the GNU Lesser General Public License as published by
Packit 6c4009
   the Free Software Foundation; either version 2.1 of the License, or
Packit 6c4009
   (at your option) any later version.
Packit 6c4009
Packit 6c4009
   This program is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 6c4009
   GNU Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public License
Packit 6c4009
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifdef HAVE_CONFIG_H
Packit 6c4009
# include <config.h>
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
Packit 6c4009
#include <plural-exp.h>
Packit 6c4009
Packit 6c4009
#if (defined __GNUC__ && !(defined __APPLE_CC_ && __APPLE_CC__ > 1) && \
Packit 6c4009
     !defined __cplusplus)					       \
Packit 6c4009
    || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
Packit 6c4009
Packit 6c4009
/* These structs are the constant expression for the germanic plural
Packit 6c4009
   form determination.  It represents the expression  "n != 1".  */
Packit 6c4009
static const struct expression plvar =
Packit 6c4009
{
Packit 6c4009
  .nargs = 0,
Packit 6c4009
  .operation = var,
Packit 6c4009
};
Packit 6c4009
static const struct expression plone =
Packit 6c4009
{
Packit 6c4009
  .nargs = 0,
Packit 6c4009
  .operation = num,
Packit 6c4009
  .val =
Packit 6c4009
  {
Packit 6c4009
    .num = 1
Packit 6c4009
  }
Packit 6c4009
};
Packit 6c4009
const struct expression GERMANIC_PLURAL =
Packit 6c4009
{
Packit 6c4009
  .nargs = 2,
Packit 6c4009
  .operation = not_equal,
Packit 6c4009
  .val =
Packit 6c4009
  {
Packit 6c4009
    .args =
Packit 6c4009
    {
Packit 6c4009
      [0] = (struct expression *) &plvar,
Packit 6c4009
      [1] = (struct expression *) &plone
Packit 6c4009
    }
Packit 6c4009
  }
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
# define INIT_GERMANIC_PLURAL()
Packit 6c4009
Packit 6c4009
#else
Packit 6c4009
Packit 6c4009
/* For compilers without support for ISO C 99 struct/union initializers:
Packit 6c4009
   Initialization at run-time.  */
Packit 6c4009
Packit 6c4009
static struct expression plvar;
Packit 6c4009
static struct expression plone;
Packit 6c4009
struct expression GERMANIC_PLURAL;
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
init_germanic_plural (void)
Packit 6c4009
{
Packit 6c4009
  if (plone.val.num == 0)
Packit 6c4009
    {
Packit 6c4009
      plvar.nargs = 0;
Packit 6c4009
      plvar.operation = var;
Packit 6c4009
Packit 6c4009
      plone.nargs = 0;
Packit 6c4009
      plone.operation = num;
Packit 6c4009
      plone.val.num = 1;
Packit 6c4009
Packit 6c4009
      GERMANIC_PLURAL.nargs = 2;
Packit 6c4009
      GERMANIC_PLURAL.operation = not_equal;
Packit 6c4009
      GERMANIC_PLURAL.val.args[0] = &plvar;
Packit 6c4009
      GERMANIC_PLURAL.val.args[1] = &plone;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
Packit 6c4009
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
EXTRACT_PLURAL_EXPRESSION (const char *nullentry,
Packit 6c4009
			   const struct expression **pluralp,
Packit 6c4009
			   unsigned long int *npluralsp)
Packit 6c4009
{
Packit 6c4009
  if (nullentry != NULL)
Packit 6c4009
    {
Packit 6c4009
      const char *plural;
Packit 6c4009
      const char *nplurals;
Packit 6c4009
Packit 6c4009
      plural = strstr (nullentry, "plural=");
Packit 6c4009
      nplurals = strstr (nullentry, "nplurals=");
Packit 6c4009
      if (plural == NULL || nplurals == NULL)
Packit 6c4009
	goto no_plural;
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  char *endp;
Packit 6c4009
	  unsigned long int n;
Packit 6c4009
	  struct parse_args args;
Packit 6c4009
Packit 6c4009
	  /* First get the number.  */
Packit 6c4009
	  nplurals += 9;
Packit 6c4009
	  while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
Packit 6c4009
	    ++nplurals;
Packit 6c4009
	  if (!(*nplurals >= '0' && *nplurals <= '9'))
Packit 6c4009
	    goto no_plural;
Packit 6c4009
#if defined HAVE_STRTOUL || defined _LIBC
Packit 6c4009
	  n = strtoul (nplurals, &endp, 10);
Packit 6c4009
#else
Packit 6c4009
	  for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
Packit 6c4009
	    n = n * 10 + (*endp - '0');
Packit 6c4009
#endif
Packit 6c4009
	  if (nplurals == endp)
Packit 6c4009
	    goto no_plural;
Packit 6c4009
	  *npluralsp = n;
Packit 6c4009
Packit 6c4009
	  /* Due to the restrictions bison imposes onto the interface of the
Packit 6c4009
	     scanner function we have to put the input string and the result
Packit 6c4009
	     passed up from the parser into the same structure which address
Packit 6c4009
	     is passed down to the parser.  */
Packit 6c4009
	  plural += 7;
Packit 6c4009
	  args.cp = plural;
Packit 6c4009
	  if (PLURAL_PARSE (&args) != 0)
Packit 6c4009
	    goto no_plural;
Packit 6c4009
	  *pluralp = args.res;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      /* By default we are using the Germanic form: singular form only
Packit 6c4009
         for `one', the plural form otherwise.  Yes, this is also what
Packit 6c4009
         English is using since English is a Germanic language.  */
Packit 6c4009
    no_plural:
Packit 6c4009
      INIT_GERMANIC_PLURAL ();
Packit 6c4009
      *pluralp = &GERMANIC_PLURAL;
Packit 6c4009
      *npluralsp = 2;
Packit 6c4009
    }
Packit 6c4009
}