No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / src / po-gram-gen.y
blobcca925760866aee3bb1451ecd05b03d3957ca8b6
1 /* GNU gettext - internationalization aids
2 Copyright (C) 1995-1996, 1998, 2000-2001, 2003 Free Software Foundation, Inc.
4 This file was written by Peter Miller <pmiller@agso.gov.au>
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 2, or (at your option)
9 any later version.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 /* Specification. */
26 #include "po-gram.h"
28 #include <stdbool.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
33 #include "str-list.h"
34 #include "po-lex.h"
35 #include "po-charset.h"
36 #include "error.h"
37 #include "xalloc.h"
38 #include "gettext.h"
39 #include "read-po-abstract.h"
41 #define _(str) gettext (str)
43 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
44 as well as gratuitiously global symbol names, so we can have multiple
45 yacc generated parsers in the same program. Note that these are only
46 the variables produced by yacc. If other parser generators (bison,
47 byacc, etc) produce additional global names that conflict at link time,
48 then those parser generators need to be fixed instead of adding those
49 names to this list. */
51 #define yymaxdepth po_gram_maxdepth
52 #define yyparse po_gram_parse
53 #define yylex po_gram_lex
54 #define yyerror po_gram_error
55 #define yylval po_gram_lval
56 #define yychar po_gram_char
57 #define yydebug po_gram_debug
58 #define yypact po_gram_pact
59 #define yyr1 po_gram_r1
60 #define yyr2 po_gram_r2
61 #define yydef po_gram_def
62 #define yychk po_gram_chk
63 #define yypgo po_gram_pgo
64 #define yyact po_gram_act
65 #define yyexca po_gram_exca
66 #define yyerrflag po_gram_errflag
67 #define yynerrs po_gram_nerrs
68 #define yyps po_gram_ps
69 #define yypv po_gram_pv
70 #define yys po_gram_s
71 #define yy_yys po_gram_yys
72 #define yystate po_gram_state
73 #define yytmp po_gram_tmp
74 #define yyv po_gram_v
75 #define yy_yyv po_gram_yyv
76 #define yyval po_gram_val
77 #define yylloc po_gram_lloc
78 #define yyreds po_gram_reds /* With YYDEBUG defined */
79 #define yytoks po_gram_toks /* With YYDEBUG defined */
80 #define yylhs po_gram_yylhs
81 #define yylen po_gram_yylen
82 #define yydefred po_gram_yydefred
83 #define yydgoto po_gram_yydgoto
84 #define yysindex po_gram_yysindex
85 #define yyrindex po_gram_yyrindex
86 #define yygindex po_gram_yygindex
87 #define yytable po_gram_yytable
88 #define yycheck po_gram_yycheck
90 static long plural_counter;
92 #define check_obsolete(value1,value2) \
93 if ((value1).obsolete != (value2).obsolete) \
94 po_gram_error_at_line (&(value2).pos, _("inconsistent use of #~"));
96 static inline void
97 do_callback_message (char *msgid, lex_pos_ty *msgid_pos, char *msgid_plural,
98 char *msgstr, size_t msgstr_len, lex_pos_ty *msgstr_pos,
99 bool obsolete)
101 /* Test for header entry. Ignore fuzziness of the header entry. */
102 if (msgid[0] == '\0' && !obsolete)
103 po_lex_charset_set (msgstr, gram_pos.file_name);
105 po_callback_message (msgid, msgid_pos, msgid_plural,
106 msgstr, msgstr_len, msgstr_pos,
107 false, obsolete);
112 %token COMMENT
113 %token DOMAIN
114 %token JUNK
115 %token MSGID
116 %token MSGID_PLURAL
117 %token MSGSTR
118 %token NAME
119 %token '[' ']'
120 %token NUMBER
121 %token STRING
123 %union
125 struct { char *string; lex_pos_ty pos; bool obsolete; } string;
126 struct { string_list_ty stringlist; lex_pos_ty pos; bool obsolete; } stringlist;
127 struct { long number; lex_pos_ty pos; bool obsolete; } number;
128 struct { lex_pos_ty pos; bool obsolete; } pos;
129 struct { struct msgstr_def rhs; lex_pos_ty pos; bool obsolete; } rhs;
132 %type <string> STRING COMMENT NAME msgid_pluralform
133 %type <stringlist> string_list
134 %type <number> NUMBER
135 %type <pos> DOMAIN MSGID MSGID_PLURAL MSGSTR '[' ']'
136 %type <rhs> pluralform pluralform_list
138 %right MSGSTR
142 msgfmt
143 : /* empty */
144 | msgfmt comment
145 | msgfmt domain
146 | msgfmt message
147 | msgfmt error
150 domain
151 : DOMAIN STRING
153 po_callback_domain ($2.string);
157 message
158 : MSGID string_list MSGSTR string_list
160 char *string2 = string_list_concat_destroy (&$2.stringlist);
161 char *string4 = string_list_concat_destroy (&$4.stringlist);
163 check_obsolete ($1, $2);
164 check_obsolete ($1, $3);
165 check_obsolete ($1, $4);
166 if (!$1.obsolete || pass_obsolete_entries)
167 do_callback_message (string2, &$1.pos, NULL,
168 string4, strlen (string4) + 1, &$3.pos,
169 $1.obsolete);
170 else
172 free (string2);
173 free (string4);
176 | MSGID string_list msgid_pluralform pluralform_list
178 char *string2 = string_list_concat_destroy (&$2.stringlist);
180 check_obsolete ($1, $2);
181 check_obsolete ($1, $3);
182 check_obsolete ($1, $4);
183 if (!$1.obsolete || pass_obsolete_entries)
184 do_callback_message (string2, &$1.pos, $3.string,
185 $4.rhs.msgstr, $4.rhs.msgstr_len, &$4.pos,
186 $1.obsolete);
187 else
189 free (string2);
190 free ($3.string);
191 free ($4.rhs.msgstr);
194 | MSGID string_list msgid_pluralform
196 check_obsolete ($1, $2);
197 check_obsolete ($1, $3);
198 po_gram_error_at_line (&$1.pos, _("missing `msgstr[]' section"));
199 string_list_destroy (&$2.stringlist);
200 free ($3.string);
202 | MSGID string_list pluralform_list
204 check_obsolete ($1, $2);
205 check_obsolete ($1, $3);
206 po_gram_error_at_line (&$1.pos, _("missing `msgid_plural' section"));
207 string_list_destroy (&$2.stringlist);
208 free ($3.rhs.msgstr);
210 | MSGID string_list
212 check_obsolete ($1, $2);
213 po_gram_error_at_line (&$1.pos, _("missing `msgstr' section"));
214 string_list_destroy (&$2.stringlist);
218 msgid_pluralform
219 : MSGID_PLURAL string_list
221 check_obsolete ($1, $2);
222 plural_counter = 0;
223 $$.string = string_list_concat_destroy (&$2.stringlist);
224 $$.pos = $1.pos;
225 $$.obsolete = $1.obsolete;
229 pluralform_list
230 : pluralform
232 $$ = $1;
234 | pluralform_list pluralform
236 check_obsolete ($1, $2);
237 $$.rhs.msgstr = (char *) xmalloc ($1.rhs.msgstr_len + $2.rhs.msgstr_len);
238 memcpy ($$.rhs.msgstr, $1.rhs.msgstr, $1.rhs.msgstr_len);
239 memcpy ($$.rhs.msgstr + $1.rhs.msgstr_len, $2.rhs.msgstr, $2.rhs.msgstr_len);
240 $$.rhs.msgstr_len = $1.rhs.msgstr_len + $2.rhs.msgstr_len;
241 free ($1.rhs.msgstr);
242 free ($2.rhs.msgstr);
243 $$.pos = $1.pos;
244 $$.obsolete = $1.obsolete;
248 pluralform
249 : MSGSTR '[' NUMBER ']' string_list
251 check_obsolete ($1, $2);
252 check_obsolete ($1, $3);
253 check_obsolete ($1, $4);
254 check_obsolete ($1, $5);
255 if ($3.number != plural_counter)
257 if (plural_counter == 0)
258 po_gram_error_at_line (&$1.pos, _("first plural form has nonzero index"));
259 else
260 po_gram_error_at_line (&$1.pos, _("plural form has wrong index"));
262 plural_counter++;
263 $$.rhs.msgstr = string_list_concat_destroy (&$5.stringlist);
264 $$.rhs.msgstr_len = strlen ($$.rhs.msgstr) + 1;
265 $$.pos = $1.pos;
266 $$.obsolete = $1.obsolete;
270 string_list
271 : STRING
273 string_list_init (&$$.stringlist);
274 string_list_append (&$$.stringlist, $1.string);
275 $$.pos = $1.pos;
276 $$.obsolete = $1.obsolete;
278 | string_list STRING
280 check_obsolete ($1, $2);
281 $$.stringlist = $1.stringlist;
282 string_list_append (&$$.stringlist, $2.string);
283 $$.pos = $1.pos;
284 $$.obsolete = $1.obsolete;
288 comment
289 : COMMENT
291 po_callback_comment_dispatcher ($1.string);