Blame gettext-runtime/intl/plural-exp.c

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