Back to index

glibc  2.9
plural-exp.c
Go to the documentation of this file.
00001 /* Expression parsing for plural form selection.
00002    Copyright (C) 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
00003    Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 # include <config.h>
00023 #endif
00024 
00025 #include <ctype.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #include "plural-exp.h"
00030 
00031 #if (defined __GNUC__ && !defined __APPLE_CC__) \
00032     || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
00033 
00034 /* These structs are the constant expression for the germanic plural
00035    form determination.  It represents the expression  "n != 1".  */
00036 static const struct expression plvar =
00037 {
00038   .nargs = 0,
00039   .operation = var,
00040 };
00041 static const struct expression plone =
00042 {
00043   .nargs = 0,
00044   .operation = num,
00045   .val =
00046   {
00047     .num = 1
00048   }
00049 };
00050 const struct expression GERMANIC_PLURAL =
00051 {
00052   .nargs = 2,
00053   .operation = not_equal,
00054   .val =
00055   {
00056     .args =
00057     {
00058       [0] = (struct expression *) &plvar,
00059       [1] = (struct expression *) &plone
00060     }
00061   }
00062 };
00063 
00064 # define INIT_GERMANIC_PLURAL()
00065 
00066 #else
00067 
00068 /* For compilers without support for ISO C 99 struct/union initializers:
00069    Initialization at run-time.  */
00070 
00071 static struct expression plvar;
00072 static struct expression plone;
00073 struct expression GERMANIC_PLURAL;
00074 
00075 static void
00076 init_germanic_plural ()
00077 {
00078   if (plone.val.num == 0)
00079     {
00080       plvar.nargs = 0;
00081       plvar.operation = var;
00082 
00083       plone.nargs = 0;
00084       plone.operation = num;
00085       plone.val.num = 1;
00086 
00087       GERMANIC_PLURAL.nargs = 2;
00088       GERMANIC_PLURAL.operation = not_equal;
00089       GERMANIC_PLURAL.val.args[0] = &plvar;
00090       GERMANIC_PLURAL.val.args[1] = &plone;
00091     }
00092 }
00093 
00094 # define INIT_GERMANIC_PLURAL() init_germanic_plural ()
00095 
00096 #endif
00097 
00098 void
00099 internal_function
00100 EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp)
00101      const char *nullentry;
00102      const struct expression **pluralp;
00103      unsigned long int *npluralsp;
00104 {
00105   if (nullentry != NULL)
00106     {
00107       const char *plural;
00108       const char *nplurals;
00109 
00110       plural = strstr (nullentry, "plural=");
00111       nplurals = strstr (nullentry, "nplurals=");
00112       if (plural == NULL || nplurals == NULL)
00113        goto no_plural;
00114       else
00115        {
00116          char *endp;
00117          unsigned long int n;
00118          struct parse_args args;
00119 
00120          /* First get the number.  */
00121          nplurals += 9;
00122          while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
00123            ++nplurals;
00124          if (!(*nplurals >= '0' && *nplurals <= '9'))
00125            goto no_plural;
00126 #if defined HAVE_STRTOUL || defined _LIBC
00127          n = strtoul (nplurals, &endp, 10);
00128 #else
00129          for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
00130            n = n * 10 + (*endp - '0');
00131 #endif
00132          if (nplurals == endp)
00133            goto no_plural;
00134          *npluralsp = n;
00135 
00136          /* Due to the restrictions bison imposes onto the interface of the
00137             scanner function we have to put the input string and the result
00138             passed up from the parser into the same structure which address
00139             is passed down to the parser.  */
00140          plural += 7;
00141          args.cp = plural;
00142          if (PLURAL_PARSE (&args) != 0)
00143            goto no_plural;
00144          *pluralp = args.res;
00145        }
00146     }
00147   else
00148     {
00149       /* By default we are using the Germanic form: singular form only
00150          for `one', the plural form otherwise.  Yes, this is also what
00151          English is using since English is a Germanic language.  */
00152     no_plural:
00153       INIT_GERMANIC_PLURAL ();
00154       *pluralp = &GERMANIC_PLURAL;
00155       *npluralsp = 2;
00156     }
00157 }