Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-tools / src / cldr-plural-exp.c
1 /* Unicode CLDR plural rule parser and converter
2    Copyright (C) 2015 Free Software Foundation, Inc.
3
4    This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include "unistr.h"
28 #include "xalloc.h"
29
30 #include "cldr-plural-exp.h"
31 #include "cldr-plural.h"
32
33 /* The grammar of Unicode CLDR plural rules is defined at:
34    http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax
35
36    This implementation only supports the "preferred" form, which
37    doesn't support obsolete keywords "in", "is", "not", and "within".
38
39    Unlike gettext, CLDR allows an unsigned decimal value as an
40    operand, in addition to unsigned integers.  For simplicity, we
41    treat decimal relations as if it has a constant truth value.
42
43    The implementation is largely based on the idea of Michele Locati's
44    cldr-to-gettext-plural-rules:
45    https://github.com/mlocati/cldr-to-gettext-plural-rules  */
46
47 void
48 cldr_plural_range_free (struct cldr_plural_range_ty *range)
49 {
50   if (range->start != range->end)
51     free (range->start);
52   free (range->end);
53   free (range);
54 }
55
56 void
57 cldr_plural_range_list_free (struct cldr_plural_range_list_ty *ranges)
58 {
59   while (ranges->nitems-- > 0)
60     cldr_plural_range_free (ranges->items[ranges->nitems]);
61   free (ranges->items);
62   free (ranges);
63 }
64
65 void
66 cldr_plural_condition_free (struct cldr_plural_condition_ty *condition)
67 {
68   if (condition->type == CLDR_PLURAL_CONDITION_AND
69       || condition->type == CLDR_PLURAL_CONDITION_OR)
70     {
71       cldr_plural_condition_free (condition->value.conditions[0]);
72       cldr_plural_condition_free (condition->value.conditions[1]);
73     }
74   else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
75     cldr_plural_relation_free (condition->value.relation);
76   free (condition);
77 }
78
79 void
80 cldr_plural_relation_free (struct cldr_plural_relation_ty *relation)
81 {
82   free (relation->expression);
83   cldr_plural_range_list_free (relation->ranges);
84   free (relation);
85 }
86
87 static void
88 cldr_plural_rule_free (struct cldr_plural_rule_ty *rule)
89 {
90   free (rule->name);
91   cldr_plural_condition_free (rule->condition);
92   free (rule);
93 }
94
95 void
96 cldr_plural_rule_list_free (struct cldr_plural_rule_list_ty *rules)
97 {
98   while (rules->nitems-- > 0)
99     cldr_plural_rule_free (rules->items[rules->nitems]);
100   free (rules->items);
101   free (rules);
102 }
103
104 struct cldr_plural_rule_list_ty *
105 cldr_plural_parse (const char *input)
106 {
107   struct cldr_plural_parse_args arg;
108
109   memset (&arg, 0, sizeof (struct cldr_plural_parse_args));
110   arg.cp = input;
111   arg.cp_end = input + strlen (input);
112   arg.result = XMALLOC (struct cldr_plural_rule_list_ty);
113   memset (arg.result, 0, sizeof (struct cldr_plural_rule_list_ty));
114
115   if (yyparse (&arg) != 0)
116     return NULL;
117
118   return arg.result;
119 }
120
121 #define OPERAND_ZERO_P(o)                               \
122     (((o)->type == CLDR_PLURAL_OPERAND_INTEGER          \
123       && (o)->value.ival == 0)                          \
124     || ((o)->type == CLDR_PLURAL_OPERAND_DECIMAL        \
125         && (o)->value.dval.d == 0))
126
127 static enum cldr_plural_condition
128 eval_relation (struct cldr_plural_relation_ty *relation)
129 {
130   switch (relation->expression->operand)
131     {
132     case 'n': case 'i':
133       {
134         /* Coerce decimal values in ranges into integers.  */
135         size_t i;
136         for (i = 0; i < relation->ranges->nitems; i++)
137           {
138             struct cldr_plural_range_ty *range = relation->ranges->items[i];
139             if (range->start->type == CLDR_PLURAL_OPERAND_DECIMAL)
140               {
141                 int truncated = (int) range->start->value.dval.d;
142                 range->start->type = CLDR_PLURAL_OPERAND_INTEGER;
143                 range->start->value.ival
144                   = range->start->value.dval.d == truncated
145                   ? truncated : truncated + 1;
146               }
147             if (range->end->type == CLDR_PLURAL_OPERAND_DECIMAL)
148               {
149                 range->end->type = CLDR_PLURAL_OPERAND_INTEGER;
150                 range->end->value.ival = (int) (range->end->value.dval.d);
151               }
152           }
153         relation->expression->operand = 'i';
154       }
155       break;
156     case 'f': case 't':
157     case 'v': case 'w':
158       {
159         /* Since plural expression in gettext only supports unsigned
160            integer, turn relations whose operand is either 'f', 't',
161            'v', or 'w' into a constant truth value.  */
162         /* FIXME: check mod?  */
163         size_t i;
164         for (i = 0; i < relation->ranges->nitems; i++)
165           {
166             struct cldr_plural_range_ty *range = relation->ranges->items[i];
167             if ((relation->type == CLDR_PLURAL_RELATION_EQUAL
168                  && (!OPERAND_ZERO_P (range->start)
169                      || !OPERAND_ZERO_P (range->end)))
170                 || (relation->type == CLDR_PLURAL_RELATION_NOT_EQUAL
171                     && (OPERAND_ZERO_P (range->start)
172                         || OPERAND_ZERO_P (range->end))))
173               return CLDR_PLURAL_CONDITION_FALSE;
174           }
175         return CLDR_PLURAL_CONDITION_TRUE;
176       }
177       break;
178     }
179   return CLDR_PLURAL_CONDITION_RELATION;
180 }
181
182 static void
183 eval_condition (struct cldr_plural_condition_ty *condition)
184 {
185   if (condition->type == CLDR_PLURAL_CONDITION_AND)
186     {
187       eval_condition (condition->value.conditions[0]);
188       eval_condition (condition->value.conditions[1]);
189
190       if (condition->value.conditions[0]->type
191           == CLDR_PLURAL_CONDITION_FALSE
192           || condition->value.conditions[1]->type
193           == CLDR_PLURAL_CONDITION_FALSE)
194         {
195           cldr_plural_condition_free (condition->value.conditions[0]);
196           cldr_plural_condition_free (condition->value.conditions[1]);
197           condition->type = CLDR_PLURAL_CONDITION_FALSE;
198         }
199       else if (condition->value.conditions[0]->type
200                == CLDR_PLURAL_CONDITION_TRUE
201                && condition->value.conditions[1]->type
202                == CLDR_PLURAL_CONDITION_TRUE)
203         {
204           cldr_plural_condition_free (condition->value.conditions[0]);
205           cldr_plural_condition_free (condition->value.conditions[1]);
206           condition->type = CLDR_PLURAL_CONDITION_TRUE;
207         }
208       else if (condition->value.conditions[0]->type
209                == CLDR_PLURAL_CONDITION_TRUE)
210         {
211           struct cldr_plural_condition_ty *original
212             = condition->value.conditions[1];
213           cldr_plural_condition_free (condition->value.conditions[0]);
214           condition->type = condition->value.conditions[1]->type;
215           condition->value = condition->value.conditions[1]->value;
216           free (original);
217         }
218       else if (condition->value.conditions[1]->type
219                == CLDR_PLURAL_CONDITION_TRUE)
220         {
221           struct cldr_plural_condition_ty *original
222             = condition->value.conditions[0];
223           cldr_plural_condition_free (condition->value.conditions[1]);
224           condition->type = condition->value.conditions[0]->type;
225           condition->value = condition->value.conditions[0]->value;
226           free (original);
227         }
228     }
229   else if (condition->type == CLDR_PLURAL_CONDITION_OR)
230     {
231       eval_condition (condition->value.conditions[0]);
232       eval_condition (condition->value.conditions[1]);
233
234       if (condition->value.conditions[0]->type
235           == CLDR_PLURAL_CONDITION_TRUE
236           || condition->value.conditions[1]->type
237           == CLDR_PLURAL_CONDITION_TRUE)
238         {
239           cldr_plural_condition_free (condition->value.conditions[0]);
240           cldr_plural_condition_free (condition->value.conditions[1]);
241           condition->type = CLDR_PLURAL_CONDITION_TRUE;
242         }
243       else if (condition->value.conditions[0]->type
244                == CLDR_PLURAL_CONDITION_FALSE
245                && condition->value.conditions[1]->type
246                == CLDR_PLURAL_CONDITION_FALSE)
247         {
248           cldr_plural_condition_free (condition->value.conditions[0]);
249           cldr_plural_condition_free (condition->value.conditions[1]);
250           condition->type = CLDR_PLURAL_CONDITION_FALSE;
251         }
252       else if (condition->value.conditions[0]->type
253                == CLDR_PLURAL_CONDITION_FALSE)
254         {
255           struct cldr_plural_condition_ty *original
256             = condition->value.conditions[1];
257           cldr_plural_condition_free (condition->value.conditions[0]);
258           condition->type = condition->value.conditions[1]->type;
259           condition->value = condition->value.conditions[1]->value;
260           free (original);
261         }
262       else if (condition->value.conditions[1]->type
263                == CLDR_PLURAL_CONDITION_FALSE)
264         {
265           struct cldr_plural_condition_ty *original
266             = condition->value.conditions[0];
267           cldr_plural_condition_free (condition->value.conditions[1]);
268           condition->type = condition->value.conditions[0]->type;
269           condition->value = condition->value.conditions[0]->value;
270           free (original);
271         }
272     }
273   else
274     {
275       enum cldr_plural_condition value =
276         eval_relation (condition->value.relation);
277       if (value == CLDR_PLURAL_CONDITION_TRUE
278           || value == CLDR_PLURAL_CONDITION_FALSE)
279         {
280           cldr_plural_relation_free (condition->value.relation);
281           condition->type = value;
282         }
283     }
284 }
285
286 #define MAX(a,b) ((a) > (b) ? (a) : (b))
287
288 static int
289 find_largest_modulus (struct cldr_plural_condition_ty *condition)
290 {
291   if (condition->type == CLDR_PLURAL_CONDITION_AND
292       || condition->type == CLDR_PLURAL_CONDITION_OR)
293     {
294       int modulus0 =
295         find_largest_modulus (condition->value.conditions[0]);
296       int modulus1 =
297         find_largest_modulus (condition->value.conditions[1]);
298       return MAX (modulus0, modulus1);
299     }
300   else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
301     return condition->value.relation->expression->mod;
302   else
303     return 0;
304 }
305
306 static int
307 find_largest_number (struct cldr_plural_condition_ty *condition)
308 {
309   if (condition->type == CLDR_PLURAL_CONDITION_AND
310       || condition->type == CLDR_PLURAL_CONDITION_OR)
311     {
312       int number0 =
313         find_largest_number (condition->value.conditions[0]);
314       int number1 =
315         find_largest_number (condition->value.conditions[1]);
316       return MAX (number0, number1);
317     }
318   else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
319     {
320       int number = 0;
321       size_t i;
322       for (i = 0; i < condition->value.relation->ranges->nitems; i++)
323         {
324           struct cldr_plural_operand_ty *operand;
325
326           operand = condition->value.relation->ranges->items[i]->end;
327           if (operand->type == CLDR_PLURAL_OPERAND_INTEGER
328               && operand->value.ival > number)
329             number = operand->value.ival;
330           else if (operand->type == CLDR_PLURAL_OPERAND_DECIMAL
331                    && operand->value.dval.d > number)
332             number = (int) operand->value.dval.d;
333         }
334       return number;
335     }
336   else
337     return 0;
338 }
339
340 static bool
341 apply_condition (struct cldr_plural_condition_ty *condition, int value)
342 {
343   if (condition->type == CLDR_PLURAL_CONDITION_AND)
344     return apply_condition (condition->value.conditions[0], value)
345       && apply_condition (condition->value.conditions[1], value);
346   else if (condition->type == CLDR_PLURAL_CONDITION_OR)
347     return apply_condition (condition->value.conditions[0], value)
348       || apply_condition (condition->value.conditions[1], value);
349   else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
350     {
351       struct cldr_plural_relation_ty *relation
352         = condition->value.relation;
353       int number = value;
354       size_t i;
355
356       if (relation->expression->mod > 0)
357         number %= relation->expression->mod;
358       for (i = 0; i < relation->ranges->nitems; i++)
359         {
360           struct cldr_plural_range_ty *range = relation->ranges->items[i];
361           if (range->start->value.ival <= number
362               && number <= range->end->value.ival)
363             return relation->type == CLDR_PLURAL_RELATION_EQUAL;
364         }
365       return relation->type != CLDR_PLURAL_RELATION_EQUAL;
366     }
367   return false;
368 }
369
370 static void
371 print_expression (struct cldr_plural_expression_ty *expression, bool space,
372                   FILE *fp)
373 {
374   if (expression->mod == 0)
375     fprintf (fp, "n");
376   else
377     fprintf (fp, space ? "n %% %d" : "n%%%d", expression->mod);
378 }
379
380 static void
381 print_relation (struct cldr_plural_relation_ty *relation,
382                 enum cldr_plural_condition parent, bool space,
383                 FILE *fp)
384 {
385   if (relation->type == CLDR_PLURAL_RELATION_EQUAL)
386     {
387       size_t i;
388       if (parent == CLDR_PLURAL_CONDITION_AND
389           && relation->ranges->nitems > 1)
390         fputc ('(', fp);
391       for (i = 0; i < relation->ranges->nitems; i++)
392         {
393           struct cldr_plural_range_ty *range = relation->ranges->items[i];
394           if (i > 0)
395             fprintf (fp, " || ");
396           if (range->start->value.ival == range->end->value.ival)
397             {
398               print_expression (relation->expression, space, fp);
399               fprintf (fp,
400                        space && relation->ranges->nitems == 1
401                        ? " == %d" : "==%d",
402                        range->start->value.ival);
403             }
404           else if (range->start->value.ival == 0)
405             {
406               print_expression (relation->expression, false, fp);
407               fprintf (fp, "<=%d", range->end->value.ival);
408             }
409           else
410             {
411               if (parent == CLDR_PLURAL_CONDITION_OR
412                   || relation->ranges->nitems > 1)
413                 fputc ('(', fp);
414               print_expression (relation->expression, false, fp);
415               fprintf (fp, ">=%d", range->start->value.ival);
416               fprintf (fp, " && ");
417               print_expression (relation->expression, false, fp);
418               fprintf (fp, "<=%d", range->end->value.ival);
419               if (parent == CLDR_PLURAL_CONDITION_OR
420                   || relation->ranges->nitems > 1)
421                 fputc (')', fp);
422             }
423         }
424       if (parent == CLDR_PLURAL_CONDITION_AND
425           && relation->ranges->nitems > 1)
426         fputc (')', fp);
427     }
428   else
429     {
430       size_t i;
431       if (parent == CLDR_PLURAL_CONDITION_OR
432           && relation->ranges->nitems > 1)
433         fputc ('(', fp);
434       for (i = 0; i < relation->ranges->nitems; i++)
435         {
436           struct cldr_plural_range_ty *range = relation->ranges->items[i];
437          if (i > 0)
438            fprintf (fp," && ");
439          if (range->start->value.ival == range->end->value.ival)
440            {
441              print_expression (relation->expression, space, fp);
442              fprintf (fp, space && relation->ranges->nitems == 1
443                       ? " != %d" : "!=%d", range->start->value.ival);
444            }
445          else if (range->start->value.ival == 0)
446            {
447              print_expression (relation->expression, false, fp);
448              fprintf (fp, ">%d", range->end->value.ival);
449            }
450          else
451            {
452              if (parent == CLDR_PLURAL_CONDITION_AND
453                  || relation->ranges->nitems > 1)
454                fputc ('(', fp);
455              print_expression (relation->expression, false, fp);
456              fprintf (fp, "<%d", range->start->value.ival);
457              fprintf (fp, " || ");
458              print_expression (relation->expression, false, fp);
459              fprintf (fp, ">%d", range->end->value.ival);
460              if (parent == CLDR_PLURAL_CONDITION_AND
461                  || relation->ranges->nitems > 1)
462                fputc (')', fp);
463            }
464         }
465       if (parent == CLDR_PLURAL_CONDITION_OR
466           && relation->ranges->nitems > 1)
467         fputc (')', fp);
468     }
469 }
470
471 static bool
472 print_condition (struct cldr_plural_condition_ty *condition,
473                  enum cldr_plural_condition parent, bool space,
474                  FILE *fp)
475 {
476   if (condition->type == CLDR_PLURAL_CONDITION_AND)
477     {
478       if (parent == CLDR_PLURAL_CONDITION_OR)
479         fputc ('(', fp);
480       print_condition (condition->value.conditions[0],
481                        CLDR_PLURAL_CONDITION_AND, false,
482                        fp);
483       fprintf (fp, " && ");
484       print_condition (condition->value.conditions[1],
485                        CLDR_PLURAL_CONDITION_AND, false,
486                        fp);
487       if (parent == CLDR_PLURAL_CONDITION_OR)
488         fputc (')', fp);
489       return true;
490     }
491   else if (condition->type == CLDR_PLURAL_CONDITION_OR)
492     {
493       if (parent == CLDR_PLURAL_CONDITION_AND)
494         fputc ('(', fp);
495       print_condition (condition->value.conditions[0],
496                        CLDR_PLURAL_CONDITION_OR, false,
497                        fp);
498       fprintf (fp, " || ");
499       print_condition (condition->value.conditions[1],
500                        CLDR_PLURAL_CONDITION_OR, false,
501                        fp);
502       if (parent == CLDR_PLURAL_CONDITION_AND)
503         fputc (')', fp);
504       return true;
505     }
506   else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
507     {
508       print_relation (condition->value.relation, parent, space, fp);
509       return true;
510     }
511   return false;
512 }
513
514 #define RULE_PRINTABLE_P(r)                                     \
515   ((r)->condition->type != CLDR_PLURAL_CONDITION_TRUE           \
516    && (r)->condition->type != CLDR_PLURAL_CONDITION_FALSE)
517
518 /* Convert n == N into n != N.  */
519 static bool
520 print_condition_negation (struct cldr_plural_condition_ty *condition, FILE *fp)
521 {
522   if (condition->type == CLDR_PLURAL_CONDITION_RELATION
523       && condition->value.relation->type == CLDR_PLURAL_RELATION_EQUAL
524       && condition->value.relation->ranges->nitems == 1
525       && condition->value.relation->ranges->items[0]->start
526       == condition->value.relation->ranges->items[0]->end)
527     {
528       fprintf (fp, "nplurals=2; plural=(n != %d);\n",
529                condition->value.relation->ranges->items[0]->start->value.ival);
530       return true;
531     }
532   return false;
533 }
534
535 /* Convert n == 0,...,N into n > N.  */
536 static bool
537 print_condition_greater (struct cldr_plural_condition_ty *condition, FILE *fp)
538 {
539   if (condition->type == CLDR_PLURAL_CONDITION_RELATION
540       && condition->value.relation->type == CLDR_PLURAL_RELATION_EQUAL)
541     {
542       int last = -1;
543       size_t i;
544       for (i = 0; i < condition->value.relation->ranges->nitems; i++)
545         {
546           struct cldr_plural_range_ty *range =
547             condition->value.relation->ranges->items[i];
548           if (range->start->type != CLDR_PLURAL_OPERAND_INTEGER
549               || range->end->type != CLDR_PLURAL_OPERAND_INTEGER
550               || range->start->value.ival != last + 1)
551             break;
552           last = range->end->value.ival;
553         }
554       if (i == condition->value.relation->ranges->nitems)
555         {
556           struct cldr_plural_range_ty *range =
557             condition->value.relation->ranges->items[i - 1];
558           fprintf (fp, "nplurals=2; plural=(n > %d);\n",
559                    range->end->value.ival);
560           return true;
561         }
562     }
563   return false;
564 }
565
566 typedef bool (*print_condition_function_ty) (struct cldr_plural_condition_ty *,
567                                              FILE *);
568 static print_condition_function_ty print_condition_functions[] =
569   {
570     print_condition_negation,
571     print_condition_greater
572   };
573
574 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
575
576 void
577 cldr_plural_rule_list_print (struct cldr_plural_rule_list_ty *rules, FILE *fp)
578 {
579   size_t i;
580   size_t count;
581   size_t nplurals;
582   int modulus_max = 0;
583
584   /* Prune trivial conditions.  */
585   for (i = 0; i < rules->nitems; i++)
586     {
587       struct cldr_plural_rule_ty *rule = rules->items[i];
588       eval_condition (rule->condition);
589     }
590
591   /* Omit trivial rules (e.g., the last rule for "ru") with the
592      following algorithm:
593      1. From all rules, find the largest modulus M
594      2. Prepare a bit vector with M elements and initialize it with zeros
595      3. Loop over the rules, until all bits are set:
596         For each value in the range [1, M], apply a rule, and flip the
597         corresponding bit if it evaluates true  */
598
599   /* Find the largest modulus.  */
600   for (i = 0; i < rules->nitems; i++)
601     {
602       struct cldr_plural_rule_ty *rule = rules->items[i];
603       int modulus = find_largest_modulus (rule->condition);
604       int number = find_largest_number (rule->condition);
605       /* If the rule contains a range whose end is larger than
606          MODULUS, we can't use MODULUS as the upper bound.  Skip
607          it.  */
608       if (modulus >= number && modulus > modulus_max)
609         modulus_max = modulus;
610     }
611
612   if (modulus_max > 0)
613     {
614       bool *values = XNMALLOC (modulus_max, bool);
615
616       memset (values, 0, sizeof (bool) * modulus_max);
617       for (i = 0; i < rules->nitems; i++)
618         {
619           struct cldr_plural_rule_ty *rule = rules->items[i];
620           int j;
621
622           for (j = 0; j < modulus_max; j++)
623             {
624               bool result = apply_condition (rule->condition, j + 1);
625               if (result)
626                 values[j] = true;
627             }
628
629           /* Check if all bits are set.  Then we can omit one more rule.  */
630           for (j = 0; j < modulus_max; j++)
631             if (values[j] == false)
632               break;
633           if (j == modulus_max)
634             break;
635         }
636
637       free (values);
638
639       while (i < rules->nitems)
640         cldr_plural_rule_free (rules->items[--rules->nitems]);
641     }
642
643   for (i = 0, nplurals = 1; i < rules->nitems; i++)
644     if (RULE_PRINTABLE_P (rules->items[i]))
645       nplurals++;
646
647   /* Special case when rules is empty.  */
648   if (nplurals == 1)
649     {
650       fprintf (fp, "nplurals=1; plural=0;\n");
651       return;
652     }
653
654   /* If we have only one printable rule, apply some heuristics.  */
655   if (nplurals == 2)
656     {
657       struct cldr_plural_condition_ty *condition;
658       size_t j;
659
660       for (j = 0; j < rules->nitems; j++)
661         if (RULE_PRINTABLE_P (rules->items[j]))
662           break;
663
664       condition = rules->items[j]->condition;
665       for (j = 0; j < SIZEOF (print_condition_functions); j++)
666         if (print_condition_functions[j] (condition, fp))
667           return;
668     }
669
670   /* If there are more printable rules, build a ternary operator.  */
671   fprintf (fp, "nplurals=%zu; plural=(", nplurals);
672   for (i = 0, count = 0; i < rules->nitems; i++)
673     {
674       struct cldr_plural_rule_ty *rule = rules->items[i];
675       if (print_condition (rule->condition,
676                            CLDR_PLURAL_CONDITION_FALSE,
677                            nplurals == 2,
678                            fp)
679           && rules->nitems > 1)
680         {
681           bool printable_left = false;
682           size_t j;
683
684           for (j = i + 1; j < rules->nitems; j++)
685             if (RULE_PRINTABLE_P (rules->items[j]))
686               printable_left = true;
687
688           if (i < rules->nitems - 1 && printable_left)
689             fprintf (fp, " ? %zu : ", count++);
690         }
691     }
692   if (rules->nitems > 1)
693     fprintf (fp, " ? %zu : %zu", count, count + 1);
694   fprintf (fp, ");\n");
695 }