1 /* GNU gettext - internationalization aids
2 Copyright (C) 1995-1996, 1998, 2000-2001, 2003, 2005-2006, 2012 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 3 of the License, or
9 (at your option) 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, see <http://www.gnu.org/licenses/>. */
34 #include "po-charset.h"
38 #include "read-catalog-abstract.h"
40 #define _(str) gettext (str)
42 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
43 as well as gratuitiously global symbol names, so we can have multiple
44 yacc generated parsers in the same program. Note that these are only
45 the variables produced by yacc. If other parser generators (bison,
46 byacc, etc) produce additional global names that conflict at link time,
47 then those parser generators need to be fixed instead of adding those
48 names to this list. */
50 #define yymaxdepth po_gram_maxdepth
51 #define yyparse po_gram_parse
52 #define yylex po_gram_lex
53 #define yyerror po_gram_error
54 #define yylval po_gram_lval
55 #define yychar po_gram_char
56 #define yydebug po_gram_debug
57 #define yypact po_gram_pact
58 #define yyr1 po_gram_r1
59 #define yyr2 po_gram_r2
60 #define yydef po_gram_def
61 #define yychk po_gram_chk
62 #define yypgo po_gram_pgo
63 #define yyact po_gram_act
64 #define yyexca po_gram_exca
65 #define yyerrflag po_gram_errflag
66 #define yynerrs po_gram_nerrs
67 #define yyps po_gram_ps
68 #define yypv po_gram_pv
70 #define yy_yys po_gram_yys
71 #define yystate po_gram_state
72 #define yytmp po_gram_tmp
74 #define yy_yyv po_gram_yyv
75 #define yyval po_gram_val
76 #define yylloc po_gram_lloc
77 #define yyreds po_gram_reds /* With YYDEBUG defined */
78 #define yytoks po_gram_toks /* With YYDEBUG defined */
79 #define yylhs po_gram_yylhs
80 #define yylen po_gram_yylen
81 #define yydefred po_gram_yydefred
82 #define yydgoto po_gram_yydgoto
83 #define yysindex po_gram_yysindex
84 #define yyrindex po_gram_yyrindex
85 #define yygindex po_gram_yygindex
86 #define yytable po_gram_yytable
87 #define yycheck po_gram_yycheck
89 static long plural_counter;
91 #define check_obsolete(value1,value2) \
92 if ((value1).obsolete != (value2).obsolete) \
93 po_gram_error_at_line (&(value2).pos, _("inconsistent use of #~"));
96 do_callback_message (char *msgctxt,
97 char *msgid, lex_pos_ty *msgid_pos, char *msgid_plural,
98 char *msgstr, size_t msgstr_len, lex_pos_ty *msgstr_pos,
100 char *prev_msgid, char *prev_msgid_plural,
103 /* Test for header entry. Ignore fuzziness of the header entry. */
104 if (msgctxt == NULL && msgid[0] == '\0' && !obsolete)
105 po_lex_charset_set (msgstr, gram_pos.file_name);
107 po_callback_message (msgctxt,
108 msgid, msgid_pos, msgid_plural,
109 msgstr, msgstr_len, msgstr_pos,
110 prev_msgctxt, prev_msgid, prev_msgid_plural,
114 #define free_message_intro(value) \
115 if ((value).prev_ctxt != NULL) \
116 free ((value).prev_ctxt); \
117 if ((value).prev_id != NULL) \
118 free ((value).prev_id); \
119 if ((value).prev_id_plural != NULL) \
120 free ((value).prev_id_plural); \
121 if ((value).ctxt != NULL) \
131 %token PREV_MSGID_PLURAL
144 struct { char *string; lex_pos_ty pos; bool obsolete; } string;
145 struct { string_list_ty stringlist; lex_pos_ty pos; bool obsolete; } stringlist;
146 struct { long number; lex_pos_ty pos; bool obsolete; } number;
147 struct { lex_pos_ty pos; bool obsolete; } pos;
148 struct { char *ctxt; char *id; char *id_plural; lex_pos_ty pos; bool obsolete; } prev;
149 struct { char *prev_ctxt; char *prev_id; char *prev_id_plural; char *ctxt; lex_pos_ty pos; bool obsolete; } message_intro;
150 struct { struct msgstr_def rhs; lex_pos_ty pos; bool obsolete; } rhs;
153 %type <string> STRING PREV_STRING COMMENT NAME
154 msg_intro prev_msg_intro msgid_pluralform prev_msgid_pluralform
155 %type <stringlist> string_list prev_string_list
156 %type <number> NUMBER
158 PREV_MSGCTXT PREV_MSGID PREV_MSGID_PLURAL
159 MSGCTXT MSGID MSGID_PLURAL MSGSTR '[' ']'
161 %type <message_intro> message_intro
162 %type <rhs> pluralform pluralform_list
180 po_callback_comment_dispatcher ($1.string);
188 po_callback_domain ($2.string);
194 : message_intro string_list MSGSTR string_list
196 char *string2 = string_list_concat_destroy (&$2.stringlist);
197 char *string4 = string_list_concat_destroy (&$4.stringlist);
199 check_obsolete ($1, $2);
200 check_obsolete ($1, $3);
201 check_obsolete ($1, $4);
202 if (!$1.obsolete || pass_obsolete_entries)
203 do_callback_message ($1.ctxt, string2, &$1.pos, NULL,
204 string4, strlen (string4) + 1, &$3.pos,
206 $1.prev_id, $1.prev_id_plural,
210 free_message_intro ($1);
215 | message_intro string_list msgid_pluralform pluralform_list
217 char *string2 = string_list_concat_destroy (&$2.stringlist);
219 check_obsolete ($1, $2);
220 check_obsolete ($1, $3);
221 check_obsolete ($1, $4);
222 if (!$1.obsolete || pass_obsolete_entries)
223 do_callback_message ($1.ctxt, string2, &$1.pos, $3.string,
224 $4.rhs.msgstr, $4.rhs.msgstr_len, &$4.pos,
226 $1.prev_id, $1.prev_id_plural,
230 free_message_intro ($1);
233 free ($4.rhs.msgstr);
236 | message_intro string_list msgid_pluralform
238 check_obsolete ($1, $2);
239 check_obsolete ($1, $3);
240 po_gram_error_at_line (&$1.pos, _("missing 'msgstr[]' section"));
241 free_message_intro ($1);
242 string_list_destroy (&$2.stringlist);
245 | message_intro string_list pluralform_list
247 check_obsolete ($1, $2);
248 check_obsolete ($1, $3);
249 po_gram_error_at_line (&$1.pos, _("missing 'msgid_plural' section"));
250 free_message_intro ($1);
251 string_list_destroy (&$2.stringlist);
252 free ($3.rhs.msgstr);
254 | message_intro string_list
256 check_obsolete ($1, $2);
257 po_gram_error_at_line (&$1.pos, _("missing 'msgstr' section"));
258 free_message_intro ($1);
259 string_list_destroy (&$2.stringlist);
269 $$.prev_id_plural = NULL;
272 $$.obsolete = $1.obsolete;
276 check_obsolete ($1, $2);
277 $$.prev_ctxt = $1.ctxt;
279 $$.prev_id_plural = $1.id_plural;
282 $$.obsolete = $2.obsolete;
288 : prev_msg_intro prev_string_list
290 check_obsolete ($1, $2);
292 $$.id = string_list_concat_destroy (&$2.stringlist);
295 $$.obsolete = $1.obsolete;
297 | prev_msg_intro prev_string_list prev_msgid_pluralform
299 check_obsolete ($1, $2);
300 check_obsolete ($1, $3);
302 $$.id = string_list_concat_destroy (&$2.stringlist);
303 $$.id_plural = $3.string;
305 $$.obsolete = $1.obsolete;
315 $$.obsolete = $1.obsolete;
317 | MSGCTXT string_list MSGID
319 check_obsolete ($1, $2);
320 check_obsolete ($1, $3);
321 $$.string = string_list_concat_destroy (&$2.stringlist);
323 $$.obsolete = $3.obsolete;
332 $$.obsolete = $1.obsolete;
334 | PREV_MSGCTXT prev_string_list PREV_MSGID
336 check_obsolete ($1, $2);
337 check_obsolete ($1, $3);
338 $$.string = string_list_concat_destroy (&$2.stringlist);
340 $$.obsolete = $3.obsolete;
346 : MSGID_PLURAL string_list
348 check_obsolete ($1, $2);
350 $$.string = string_list_concat_destroy (&$2.stringlist);
352 $$.obsolete = $1.obsolete;
356 prev_msgid_pluralform
357 : PREV_MSGID_PLURAL prev_string_list
359 check_obsolete ($1, $2);
360 $$.string = string_list_concat_destroy (&$2.stringlist);
362 $$.obsolete = $1.obsolete;
372 | pluralform_list pluralform
374 check_obsolete ($1, $2);
375 $$.rhs.msgstr = XNMALLOC ($1.rhs.msgstr_len + $2.rhs.msgstr_len, char);
376 memcpy ($$.rhs.msgstr, $1.rhs.msgstr, $1.rhs.msgstr_len);
377 memcpy ($$.rhs.msgstr + $1.rhs.msgstr_len, $2.rhs.msgstr, $2.rhs.msgstr_len);
378 $$.rhs.msgstr_len = $1.rhs.msgstr_len + $2.rhs.msgstr_len;
379 free ($1.rhs.msgstr);
380 free ($2.rhs.msgstr);
382 $$.obsolete = $1.obsolete;
387 : MSGSTR '[' NUMBER ']' string_list
389 check_obsolete ($1, $2);
390 check_obsolete ($1, $3);
391 check_obsolete ($1, $4);
392 check_obsolete ($1, $5);
393 if ($3.number != plural_counter)
395 if (plural_counter == 0)
396 po_gram_error_at_line (&$1.pos, _("first plural form has nonzero index"));
398 po_gram_error_at_line (&$1.pos, _("plural form has wrong index"));
401 $$.rhs.msgstr = string_list_concat_destroy (&$5.stringlist);
402 $$.rhs.msgstr_len = strlen ($$.rhs.msgstr) + 1;
404 $$.obsolete = $1.obsolete;
412 string_list_init (&$$.stringlist);
413 string_list_append (&$$.stringlist, $1.string);
415 $$.obsolete = $1.obsolete;
419 check_obsolete ($1, $2);
420 $$.stringlist = $1.stringlist;
421 string_list_append (&$$.stringlist, $2.string);
423 $$.obsolete = $1.obsolete;
430 string_list_init (&$$.stringlist);
431 string_list_append (&$$.stringlist, $1.string);
433 $$.obsolete = $1.obsolete;
435 | prev_string_list PREV_STRING
437 check_obsolete ($1, $2);
438 $$.stringlist = $1.stringlist;
439 string_list_append (&$$.stringlist, $2.string);
441 $$.obsolete = $1.obsolete;