Back to index

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