Back to index

tetex-bin  3.0
plural-exp.c
Go to the documentation of this file.
00001 /* Expression parsing for plural form selection.
00002    Copyright (C) 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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__ && !defined __APPLE_CC__) \
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, struct expression **pluralp,
00100                         unsigned long int *npluralsp)
00101 {
00102   if (nullentry != NULL)
00103     {
00104       const char *plural;
00105       const char *nplurals;
00106 
00107       plural = strstr (nullentry, "plural=");
00108       nplurals = strstr (nullentry, "nplurals=");
00109       if (plural == NULL || nplurals == NULL)
00110        goto no_plural;
00111       else
00112        {
00113          char *endp;
00114          unsigned long int n;
00115          struct parse_args args;
00116 
00117          /* First get the number.  */
00118          nplurals += 9;
00119          while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
00120            ++nplurals;
00121          if (!(*nplurals >= '0' && *nplurals <= '9'))
00122            goto no_plural;
00123 #if defined HAVE_STRTOUL || defined _LIBC
00124          n = strtoul (nplurals, &endp, 10);
00125 #else
00126          for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
00127            n = n * 10 + (*endp - '0');
00128 #endif
00129          if (nplurals == endp)
00130            goto no_plural;
00131          *npluralsp = n;
00132 
00133          /* Due to the restrictions bison imposes onto the interface of the
00134             scanner function we have to put the input string and the result
00135             passed up from the parser into the same structure which address
00136             is passed down to the parser.  */
00137          plural += 7;
00138          args.cp = plural;
00139          if (PLURAL_PARSE (&args) != 0)
00140            goto no_plural;
00141          *pluralp = args.res;
00142        }
00143     }
00144   else
00145     {
00146       /* By default we are using the Germanic form: singular form only
00147          for `one', the plural form otherwise.  Yes, this is also what
00148          English is using since English is a Germanic language.  */
00149     no_plural:
00150       INIT_GERMANIC_PLURAL ();
00151       *pluralp = &GERMANIC_PLURAL;
00152       *npluralsp = 2;
00153     }
00154 }