diff options
author | Ulrich Drepper <drepper@redhat.com> | 2001-03-20 01:00:20 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2001-03-20 01:00:20 +0000 |
commit | 4a4d50f3728ae901ad94e33ee53270906866371d (patch) | |
tree | 70901731cf88b75c9bb0291dd1bce0dc1204844f /intl/plural.y | |
parent | f2615995a753b80dd8d9fce55f5e87e8105f2d82 (diff) | |
download | glibc-4a4d50f3728ae901ad94e33ee53270906866371d.tar.gz glibc-4a4d50f3728ae901ad94e33ee53270906866371d.tar.xz glibc-4a4d50f3728ae901ad94e33ee53270906866371d.zip |
Update.
2001-03-17 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c (_nl_load_domain) [!_LIBC]: Use fstat, not fstat64. 2001-03-17 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h (struct expression): Add operators lnot, less_than, greater_than, less_or_equal, greater_or_equal. Replace args2/args3 union by a 'nargs' counter and an 'args[]' array. * intl/plural.y: Don't include stdarg.h. (new_exp): Take an array of arguments instead of varargs. (new_exp_0, new_exp_1, new_exp_2, new_exp_3): New functions. ('?' ':'): Make right-associative. (EQUOP2): New token, replaces '=' and '!'. (CMPOP2): New token. (ADDOP2): New token, replaces '+' and '-'. (MULOP2): New token, replaces '*', '/' and '%'. ('!'): New token. (exp): Add rules for CMPOP2 and '!'. Don't call YYABORT. (start): Call YYABORT here. (FREE_EXPRESSION): Update. (yylex): Don't skip "\\n". Recognize comparison and '!' operators. Update for new token symbols. * intl/loadmsgcat.c (plvar, plone, germanic_plural, init_germanic_plural): Update. * intl/dcigettext.c (_nl_find_msg): Optimize for space. (plural_eval): Recognize comparison and '!' operators. Optimize for space. 2001-03-10 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c (_nl_load_domain): locale_charset() doesn't return NULL any more. 2001-01-05 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c: Include headers needed for alloca(). (freea): New macro. (_nl_load_domain): Add fallback code for platforms lacking alloca. * intl/localealias.c: (ADD_BLOCK, FREE_BLOCK): Remove macros. (freea): New macro. (read_alias_file): Simplify fallback code for platforms lacking alloca. 2001-01-07 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h (__gettextdebug): Remove declaration. (__gettext_free_exp, __gettextparse): Convert prototype to K&R C syntax. (gettext_free_exp__, gettextparse__): New non-libc declarations. * intl/plural.y [!_LIBC]: Define gettextparse__, gettext_free_exp__, not __gettextparse, __gettext_free_exp. * intl/loadmsgcat.c [!_LIBC]: Use gettextparse__, not __gettextparse. 2001-02-24 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c: Update comment about HAVE_LOCALE_NULL. 2001-01-05 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c (_nl_load_domain): Add fallback code for platforms lacking strtoul, like SunOS4. 2001-01-05 Bruno Haible <haible@clisp.cons.org> * intl/l10nflist.c (_nl_normalize_codeset): Use tolower, not _tolower. 2001-01-05 Bruno Haible <haible@clisp.cons.org> * intl/bindtextdom.c (set_binding_values): Convert prototype to K&R C syntax. * intl/dcigettext.c (transcmp): Convert to K&R C syntax. * intl/explodename.c (_nl_find_language): Convert to K&R C syntax. * intl/plural.y (__gettext_free_exp, yylex, yyerror): Convert to K&R C syntax. 2001-01-07 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h (gettext__, dgettext__, dcgettext__, textdomain__, bindtextdomain__, bind_textdomain_codeset__): New declarations, from old libgettext.h. * intl/bindtextdom.c: Include libgnuintl.h instead of libgettext.h. * intl/dcgettext.c: Likewise. * intl/dcigettext.c: Likewise. * intl/dcngettext.c: Likewise. * intl/dngettext.c: Likewise. * intl/finddomain.c: Likewise. * intl/ngettext.c: Likewise. * intl/textdomain.c: Likewise. * intl/dgettext.c: Include libgnuintl.h instead of libgettext.h. Include gettextP.h. * intl/gettext.c: Likewise. Don't include locale.h. 2001-03-17 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h (ZERO): New macro. (struct binding): Always use ZERO. * intl/bindtextdom.c (offsetof): Provide fallback for platforms that lack it, like SunOS4. (set_binding_values): Use offsetof, not sizeof. * intl/dcigettext.c (offsetof): Provide fallback for platforms that lack it, like SunOS4. (ZERO): Remove macro. (struct transmem_list): Use ZERO. (DCIGETTEXT): Use offsetof, not sizeof. 2001-03-17 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h: Include <stddef.h>. Include gettext.h, for nls_uint32. * intl/bindtextdom.c: Don't include gettext.h. * intl/dcgettext.c: Likewise. * intl/dcigettext.c: Likewise. * intl/dcngettext.c: Likewise. * intl/dngettext.c: Likewise. * intl/finddomain.c: Likewise. * intl/localealias.c: Likewise. * intl/ngettext.c: Likewise. * intl/plural.y: Likewise. * intl/textdomain.c: Likewise. 2001-03-17 Bruno Haible <haible@clisp.cons.org> * intl/gettext.h: Don't include <stdio.h>. 2001-03-17 Bruno Haible <haible@clisp.cons.org> * intl/Makefile (CPPFLAGS): Set LOCALEDIR instead of GNULOCALEDIR. * intl/dcigettext.c (_nl_default_dirname): Initialize with LOCALEDIR.
Diffstat (limited to 'intl/plural.y')
-rw-r--r-- | intl/plural.y | 328 |
1 files changed, 214 insertions, 114 deletions
diff --git a/intl/plural.y b/intl/plural.y index f14dc29fd3..e85f7b8a65 100644 --- a/intl/plural.y +++ b/intl/plural.y @@ -22,11 +22,20 @@ # include <config.h> #endif -#include <stdarg.h> #include <stdlib.h> -#include "gettext.h" #include "gettextP.h" +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define FREE_EXPRESSION __gettext_free_exp +#else +# define FREE_EXPRESSION gettext_free_exp__ +# define __gettextparse gettextparse__ +#endif + #define YYLEX_PARAM &((struct parse_args *) arg)->cp #define YYPARSE_PARAM arg %} @@ -35,22 +44,124 @@ %union { unsigned long int num; + enum operator op; struct expression *exp; } %{ /* Prototypes for local functions. */ -static struct expression *new_exp (enum operator op, int n, ...); -static int yylex (YYSTYPE *lval, const char **pexp); -static void yyerror (const char *str); +static struct expression *new_exp PARAMS ((int nargs, enum operator op, + struct expression * const *args)); +static inline struct expression *new_exp_0 PARAMS ((enum operator op)); +static inline struct expression *new_exp_1 PARAMS ((enum operator op, + struct expression *right)); +static struct expression *new_exp_2 PARAMS ((enum operator op, + struct expression *left, + struct expression *right)); +static inline struct expression *new_exp_3 PARAMS ((enum operator op, + struct expression *bexp, + struct expression *tbranch, + struct expression *fbranch)); +static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); +static void yyerror PARAMS ((const char *str)); + +/* Allocation of expressions. */ + +static struct expression * +new_exp (nargs, op, args) + int nargs; + enum operator op; + struct expression * const *args; +{ + int i; + struct expression *newp; + + /* If any of the argument could not be malloc'ed, just return NULL. */ + for (i = nargs - 1; i >= 0; i--) + if (args[i] == NULL) + goto fail; + + /* Allocate a new expression. */ + newp = (struct expression *) malloc (sizeof (*newp)); + if (newp != NULL) + { + newp->nargs = nargs; + newp->operation = op; + for (i = nargs - 1; i >= 0; i--) + newp->val.args[i] = args[i]; + return newp; + } + + fail: + for (i = nargs - 1; i >= 0; i--) + FREE_EXPRESSION (args[i]); + + return NULL; +} + +static inline struct expression * +new_exp_0 (op) + enum operator op; +{ + return new_exp (0, op, NULL); +} + +static inline struct expression * +new_exp_1 (op, right) + enum operator op; + struct expression *right; +{ + struct expression *args[1]; + + args[0] = right; + return new_exp (1, op, args); +} + +static struct expression * +new_exp_2 (op, left, right) + enum operator op; + struct expression *left; + struct expression *right; +{ + struct expression *args[2]; + + args[0] = left; + args[1] = right; + return new_exp (2, op, args); +} + +static inline struct expression * +new_exp_3 (op, bexp, tbranch, fbranch) + enum operator op; + struct expression *bexp; + struct expression *tbranch; + struct expression *fbranch; +{ + struct expression *args[3]; + + args[0] = bexp; + args[1] = tbranch; + args[2] = fbranch; + return new_exp (3, op, args); +} + %} -%left '?' -%left '|' -%left '&' -%left '=', '!' -%left '+', '-' -%left '*', '/', '%' +/* This declares that all operators have the same associativity and the + precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. + There is no unary minus and no bitwise operators. + Operators with the same syntactic behaviour have been merged into a single + token, to save space in the array generated by bison. */ +%right '?' /* ? */ +%left '|' /* || */ +%left '&' /* && */ +%left EQUOP2 /* == != */ +%left CMPOP2 /* < > <= >= */ +%left ADDOP2 /* + - */ +%left MULOP2 /* * / % */ +%right '!' /* ! */ + +%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2 %token <num> NUMBER %type <exp> exp @@ -58,143 +169,81 @@ static void yyerror (const char *str); start: exp { + if ($1 == NULL) + YYABORT; ((struct parse_args *) arg)->res = $1; } ; exp: exp '?' exp ':' exp { - if (($$ = new_exp (qmop, 3, $1, $3, $5)) == NULL) - YYABORT + $$ = new_exp_3 (qmop, $1, $3, $5); } | exp '|' exp { - if (($$ = new_exp (lor, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_2 (lor, $1, $3); } | exp '&' exp { - if (($$ = new_exp (land, 2, $1, $3)) == NULL) - YYABORT - } - | exp '=' exp - { - if (($$ = new_exp (equal, 2, $1, $3)) == NULL) - YYABORT - } - | exp '!' exp - { - if (($$ = new_exp (not_equal, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_2 (land, $1, $3); } - | exp '+' exp + | exp EQUOP2 exp { - if (($$ = new_exp (plus, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_2 ($2, $1, $3); } - | exp '-' exp + | exp CMPOP2 exp { - if (($$ = new_exp (minus, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_2 ($2, $1, $3); } - | exp '*' exp + | exp ADDOP2 exp { - if (($$ = new_exp (mult, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_2 ($2, $1, $3); } - | exp '/' exp + | exp MULOP2 exp { - if (($$ = new_exp (divide, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_2 ($2, $1, $3); } - | exp '%' exp + | '!' exp { - if (($$ = new_exp (module, 2, $1, $3)) == NULL) - YYABORT + $$ = new_exp_1 (lnot, $2); } | 'n' { - if (($$ = new_exp (var, 0)) == NULL) - YYABORT + $$ = new_exp_0 (var); } | NUMBER { - if (($$ = new_exp (num, 0)) == NULL) - YYABORT; - $$->val.num = $1 + if (($$ = new_exp_0 (num)) != NULL) + $$->val.num = $1; } | '(' exp ')' { - $$ = $2 + $$ = $2; } ; %% -static struct expression * -new_exp (enum operator op, int n, ...) -{ - struct expression *newp = (struct expression *) calloc (1, sizeof (*newp)); - va_list va; - - va_start (va, n); - - if (newp == NULL) - while (n-- > 0) - __gettext_free_exp (va_arg (va, struct expression *)); - else - { - newp->operation = op; - if (n > 0) - { - newp->val.args3.bexp = va_arg (va, struct expression *); - newp->val.args3.tbranch = va_arg (va, struct expression *); - - if (n > 2) - newp->val.args3.fbranch = va_arg (va, struct expression *); - - if (newp->val.args3.bexp == NULL - || newp->val.args3.tbranch == NULL - || (n > 2 && newp->val.args3.fbranch == NULL)) - { - __gettext_free_exp (newp); - newp = NULL; - } - } - } - - va_end (va); - - return newp; -} - void internal_function -__gettext_free_exp (struct expression *exp) +FREE_EXPRESSION (exp) + struct expression *exp; { if (exp == NULL) return; /* Handle the recursive case. */ - switch (exp->operation) + switch (exp->nargs) { - case qmop: - __gettext_free_exp (exp->val.args3.fbranch); + case 3: + FREE_EXPRESSION (exp->val.args[2]); + /* FALLTHROUGH */ + case 2: + FREE_EXPRESSION (exp->val.args[1]); + /* FALLTHROUGH */ + case 1: + FREE_EXPRESSION (exp->val.args[0]); /* FALLTHROUGH */ - - case mult: - case divide: - case module: - case plus: - case minus: - case equal: - case not_equal: - case land: - case lor: - __gettext_free_exp (exp->val.args2.right); - __gettext_free_exp (exp->val.args2.left); - break; - default: break; } @@ -204,19 +253,15 @@ __gettext_free_exp (struct expression *exp) static int -yylex (YYSTYPE *lval, const char **pexp) +yylex (lval, pexp) + YYSTYPE *lval; + const char **pexp; { const char *exp = *pexp; int result; while (1) { - if (exp[0] == '\\' && exp[1] == '\n') - { - exp += 2; - continue; - } - if (exp[0] == '\0') { *pexp = exp; @@ -248,13 +293,25 @@ yylex (YYSTYPE *lval, const char **pexp) break; case '=': - case '!': if (exp[0] == '=') - ++exp; + { + ++exp; + lval->op = equal; + result = EQUOP2; + } else result = YYERRCODE; break; + case '!': + if (exp[0] == '=') + { + ++exp; + lval->op = not_equal; + result = EQUOP2; + } + break; + case '&': case '|': if (exp[0] == result) @@ -263,12 +320,54 @@ yylex (YYSTYPE *lval, const char **pexp) result = YYERRCODE; break; - case 'n': + case '<': + if (exp[0] == '=') + { + ++exp; + lval->op = less_or_equal; + } + else + lval->op = less_than; + result = CMPOP2; + break; + + case '>': + if (exp[0] == '=') + { + ++exp; + lval->op = greater_or_equal; + } + else + lval->op = greater_than; + result = CMPOP2; + break; + case '*': + lval->op = mult; + result = MULOP2; + break; + case '/': + lval->op = divide; + result = MULOP2; + break; + case '%': + lval->op = module; + result = MULOP2; + break; + case '+': + lval->op = plus; + result = ADDOP2; + break; + case '-': + lval->op = minus; + result = ADDOP2; + break; + + case 'n': case '?': case ':': case '(': @@ -299,7 +398,8 @@ yylex (YYSTYPE *lval, const char **pexp) static void -yyerror (const char *str) +yyerror (str) + const char *str; { /* Do nothing. We don't print error messages here. */ } |