1 1.1 christos /* $NetBSD: plural-exp.c,v 1.1.1.1 2016/01/10 21:36:18 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* Expression parsing for plural form selection. 4 1.1 christos Copyright (C) 2000, 2001 Free Software Foundation, Inc. 5 1.1 christos Written by Ulrich Drepper <drepper (at) cygnus.com>, 2000. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify it 8 1.1 christos under the terms of the GNU Library General Public License as published 9 1.1 christos by the Free Software Foundation; either version 2, or (at your option) 10 1.1 christos any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 1.1 christos Library General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU Library General Public 18 1.1 christos License along with this program; if not, write to the Free Software 19 1.1 christos Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 1.1 christos USA. */ 21 1.1 christos 22 1.1 christos #ifdef HAVE_CONFIG_H 23 1.1 christos # include <config.h> 24 1.1 christos #endif 25 1.1 christos 26 1.1 christos #include <ctype.h> 27 1.1 christos #include <stdlib.h> 28 1.1 christos #include <string.h> 29 1.1 christos 30 1.1 christos #include "plural-exp.h" 31 1.1 christos 32 1.1 christos #if (defined __GNUC__ && !defined __APPLE_CC__) \ 33 1.1 christos || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) 34 1.1 christos 35 1.1 christos /* These structs are the constant expression for the germanic plural 36 1.1 christos form determination. It represents the expression "n != 1". */ 37 1.1 christos static const struct expression plvar = 38 1.1 christos { 39 1.1 christos .nargs = 0, 40 1.1 christos .operation = var, 41 1.1 christos }; 42 1.1 christos static const struct expression plone = 43 1.1 christos { 44 1.1 christos .nargs = 0, 45 1.1 christos .operation = num, 46 1.1 christos .val = 47 1.1 christos { 48 1.1 christos .num = 1 49 1.1 christos } 50 1.1 christos }; 51 1.1 christos struct expression GERMANIC_PLURAL = 52 1.1 christos { 53 1.1 christos .nargs = 2, 54 1.1 christos .operation = not_equal, 55 1.1 christos .val = 56 1.1 christos { 57 1.1 christos .args = 58 1.1 christos { 59 1.1 christos [0] = (struct expression *) &plvar, 60 1.1 christos [1] = (struct expression *) &plone 61 1.1 christos } 62 1.1 christos } 63 1.1 christos }; 64 1.1 christos 65 1.1 christos # define INIT_GERMANIC_PLURAL() 66 1.1 christos 67 1.1 christos #else 68 1.1 christos 69 1.1 christos /* For compilers without support for ISO C 99 struct/union initializers: 70 1.1 christos Initialization at run-time. */ 71 1.1 christos 72 1.1 christos static struct expression plvar; 73 1.1 christos static struct expression plone; 74 1.1 christos struct expression GERMANIC_PLURAL; 75 1.1 christos 76 1.1 christos static void 77 1.1 christos init_germanic_plural () 78 1.1 christos { 79 1.1 christos if (plone.val.num == 0) 80 1.1 christos { 81 1.1 christos plvar.nargs = 0; 82 1.1 christos plvar.operation = var; 83 1.1 christos 84 1.1 christos plone.nargs = 0; 85 1.1 christos plone.operation = num; 86 1.1 christos plone.val.num = 1; 87 1.1 christos 88 1.1 christos GERMANIC_PLURAL.nargs = 2; 89 1.1 christos GERMANIC_PLURAL.operation = not_equal; 90 1.1 christos GERMANIC_PLURAL.val.args[0] = &plvar; 91 1.1 christos GERMANIC_PLURAL.val.args[1] = &plone; 92 1.1 christos } 93 1.1 christos } 94 1.1 christos 95 1.1 christos # define INIT_GERMANIC_PLURAL() init_germanic_plural () 96 1.1 christos 97 1.1 christos #endif 98 1.1 christos 99 1.1 christos void 100 1.1 christos internal_function 101 1.1 christos EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp) 102 1.1 christos const char *nullentry; 103 1.1 christos struct expression **pluralp; 104 1.1 christos unsigned long int *npluralsp; 105 1.1 christos { 106 1.1 christos if (nullentry != NULL) 107 1.1 christos { 108 1.1 christos const char *plural; 109 1.1 christos const char *nplurals; 110 1.1 christos 111 1.1 christos plural = strstr (nullentry, "plural="); 112 1.1 christos nplurals = strstr (nullentry, "nplurals="); 113 1.1 christos if (plural == NULL || nplurals == NULL) 114 1.1 christos goto no_plural; 115 1.1 christos else 116 1.1 christos { 117 1.1 christos char *endp; 118 1.1 christos unsigned long int n; 119 1.1 christos struct parse_args args; 120 1.1 christos 121 1.1 christos /* First get the number. */ 122 1.1 christos nplurals += 9; 123 1.1 christos while (*nplurals != '\0' && isspace ((unsigned char) *nplurals)) 124 1.1 christos ++nplurals; 125 1.1 christos if (!(*nplurals >= '0' && *nplurals <= '9')) 126 1.1 christos goto no_plural; 127 1.1 christos #if defined HAVE_STRTOUL || defined _LIBC 128 1.1 christos n = strtoul (nplurals, &endp, 10); 129 1.1 christos #else 130 1.1 christos for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++) 131 1.1 christos n = n * 10 + (*endp - '0'); 132 1.1 christos #endif 133 1.1 christos if (nplurals == endp) 134 1.1 christos goto no_plural; 135 1.1 christos *npluralsp = n; 136 1.1 christos 137 1.1 christos /* Due to the restrictions bison imposes onto the interface of the 138 1.1 christos scanner function we have to put the input string and the result 139 1.1 christos passed up from the parser into the same structure which address 140 1.1 christos is passed down to the parser. */ 141 1.1 christos plural += 7; 142 1.1 christos args.cp = plural; 143 1.1 christos if (PLURAL_PARSE (&args) != 0) 144 1.1 christos goto no_plural; 145 1.1 christos *pluralp = args.res; 146 1.1 christos } 147 1.1 christos } 148 1.1 christos else 149 1.1 christos { 150 1.1 christos /* By default we are using the Germanic form: singular form only 151 1.1 christos for `one', the plural form otherwise. Yes, this is also what 152 1.1 christos English is using since English is a Germanic language. */ 153 1.1 christos no_plural: 154 1.1 christos INIT_GERMANIC_PLURAL (); 155 1.1 christos *pluralp = &GERMANIC_PLURAL; 156 1.1 christos *npluralsp = 2; 157 1.1 christos } 158 1.1 christos } 159