1 /* GNU gettext - internationalization aids
2 Copyright (C) 1995-1996, 1998, 2000-2001, 2003, 2005-2006, 2012, 2015
3 Free Software Foundation, Inc.
5 This file was written by Peter Miller <pmiller@agso.gov.au>
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
35 #include "po-charset.h"
39 #include "read-catalog-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
71 #define yy_yys po_gram_yys
72 #define yystate po_gram_state
73 #define yytmp po_gram_tmp
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 #~"));
97 do_callback_message (char *msgctxt,
98 char *msgid, lex_pos_ty *msgid_pos, char *msgid_plural,
99 char *msgstr, size_t msgstr_len, lex_pos_ty *msgstr_pos,
101 char *prev_msgid, char *prev_msgid_plural,
104 /* Test for header entry. Ignore fuzziness of the header entry. */
105 if (msgctxt == NULL && msgid[0] == '\0' && !obsolete)
106 po_lex_charset_set (msgstr, gram_pos.file_name);
108 po_callback_message (msgctxt,
109 msgid, msgid_pos, msgid_plural,
110 msgstr, msgstr_len, msgstr_pos,
111 prev_msgctxt, prev_msgid, prev_msgid_plural,
115 #define free_message_intro(value) \
116 if ((value).prev_ctxt != NULL) \
117 free ((value).prev_ctxt); \
118 if ((value).prev_id != NULL) \
119 free ((value).prev_id); \
120 if ((value).prev_id_plural != NULL) \
121 free ((value).prev_id_plural); \
122 if ((value).ctxt != NULL) \
132 %token PREV_MSGID_PLURAL
145 struct { char *string; lex_pos_ty pos; bool obsolete; } string;
146 struct { string_list_ty stringlist; lex_pos_ty pos; bool obsolete; } stringlist;
147 struct { long number; lex_pos_ty pos; bool obsolete; } number;
148 struct { lex_pos_ty pos; bool obsolete; } pos;
149 struct { char *ctxt; char *id; char *id_plural; lex_pos_ty pos; bool obsolete; } prev;
150 struct { char *prev_ctxt; char *prev_id; char *prev_id_plural; char *ctxt; lex_pos_ty pos; bool obsolete; } message_intro;
151 struct { struct msgstr_def rhs; lex_pos_ty pos; bool obsolete; } rhs;
154 %type <string> STRING PREV_STRING COMMENT NAME
155 msg_intro prev_msg_intro msgid_pluralform prev_msgid_pluralform
156 %type <stringlist> string_list prev_string_list
157 %type <number> NUMBER
159 PREV_MSGCTXT PREV_MSGID PREV_MSGID_PLURAL
160 MSGCTXT MSGID MSGID_PLURAL MSGSTR '[' ']'
162 %type <message_intro> message_intro
163 %type <rhs> pluralform pluralform_list
181 po_callback_comment_dispatcher ($1.string);
189 po_callback_domain ($2.string);
195 : message_intro string_list MSGSTR string_list
197 char *string2 = string_list_concat_destroy (&$2.stringlist);
198 char *string4 = string_list_concat_destroy (&$4.stringlist);
200 check_obsolete ($1, $2);
201 check_obsolete ($1, $3);
202 check_obsolete ($1, $4);
203 if (!$1.obsolete || pass_obsolete_entries)
204 do_callback_message ($1.ctxt, string2, &$1.pos, NULL,
205 string4, strlen (string4) + 1, &$3.pos,
207 $1.prev_id, $1.prev_id_plural,
211 free_message_intro ($1);
216 | message_intro string_list msgid_pluralform pluralform_list
218 char *string2 = string_list_concat_destroy (&$2.stringlist);
220 check_obsolete ($1, $2);
221 check_obsolete ($1, $3);
222 check_obsolete ($1, $4);
223 if (!$1.obsolete || pass_obsolete_entries)
225 do_callback_message ($1.ctxt, string2, &$1.pos, $3.string,
226 $4.rhs.msgstr, $4.rhs.msgstr_len, &$4.pos,
228 $1.prev_id, $1.prev_id_plural,
234 free_message_intro ($1);
237 free ($4.rhs.msgstr);
240 | message_intro string_list msgid_pluralform
242 check_obsolete ($1, $2);
243 check_obsolete ($1, $3);
244 po_gram_error_at_line (&$1.pos, _("missing 'msgstr[]' section"));
245 free_message_intro ($1);
246 string_list_destroy (&$2.stringlist);
249 | message_intro string_list pluralform_list
251 check_obsolete ($1, $2);
252 check_obsolete ($1, $3);
253 po_gram_error_at_line (&$1.pos, _("missing 'msgid_plural' section"));
254 free_message_intro ($1);
255 string_list_destroy (&$2.stringlist);
256 free ($3.rhs.msgstr);
258 | message_intro string_list
260 check_obsolete ($1, $2);
261 po_gram_error_at_line (&$1.pos, _("missing 'msgstr' section"));
262 free_message_intro ($1);
263 string_list_destroy (&$2.stringlist);
273 $$.prev_id_plural = NULL;
276 $$.obsolete = $1.obsolete;
280 check_obsolete ($1, $2);
281 $$.prev_ctxt = $1.ctxt;
283 $$.prev_id_plural = $1.id_plural;
286 $$.obsolete = $2.obsolete;
292 : prev_msg_intro prev_string_list
294 check_obsolete ($1, $2);
296 $$.id = string_list_concat_destroy (&$2.stringlist);
299 $$.obsolete = $1.obsolete;
301 | prev_msg_intro prev_string_list prev_msgid_pluralform
303 check_obsolete ($1, $2);
304 check_obsolete ($1, $3);
306 $$.id = string_list_concat_destroy (&$2.stringlist);
307 $$.id_plural = $3.string;
309 $$.obsolete = $1.obsolete;
319 $$.obsolete = $1.obsolete;
321 | MSGCTXT string_list MSGID
323 check_obsolete ($1, $2);
324 check_obsolete ($1, $3);
325 $$.string = string_list_concat_destroy (&$2.stringlist);
327 $$.obsolete = $3.obsolete;
336 $$.obsolete = $1.obsolete;
338 | PREV_MSGCTXT prev_string_list PREV_MSGID
340 check_obsolete ($1, $2);
341 check_obsolete ($1, $3);
342 $$.string = string_list_concat_destroy (&$2.stringlist);
344 $$.obsolete = $3.obsolete;
350 : MSGID_PLURAL string_list
352 check_obsolete ($1, $2);
354 $$.string = string_list_concat_destroy (&$2.stringlist);
356 $$.obsolete = $1.obsolete;
360 prev_msgid_pluralform
361 : PREV_MSGID_PLURAL prev_string_list
363 check_obsolete ($1, $2);
364 $$.string = string_list_concat_destroy (&$2.stringlist);
366 $$.obsolete = $1.obsolete;
376 | pluralform_list pluralform
378 check_obsolete ($1, $2);
379 $$.rhs.msgstr = XNMALLOC ($1.rhs.msgstr_len + $2.rhs.msgstr_len, char);
380 memcpy ($$.rhs.msgstr, $1.rhs.msgstr, $1.rhs.msgstr_len);
381 memcpy ($$.rhs.msgstr + $1.rhs.msgstr_len, $2.rhs.msgstr, $2.rhs.msgstr_len);
382 $$.rhs.msgstr_len = $1.rhs.msgstr_len + $2.rhs.msgstr_len;
383 free ($1.rhs.msgstr);
384 free ($2.rhs.msgstr);
386 $$.obsolete = $1.obsolete;
391 : MSGSTR '[' NUMBER ']' string_list
393 check_obsolete ($1, $2);
394 check_obsolete ($1, $3);
395 check_obsolete ($1, $4);
396 check_obsolete ($1, $5);
397 if ($3.number != plural_counter)
399 if (plural_counter == 0)
400 po_gram_error_at_line (&$1.pos, _("first plural form has nonzero index"));
402 po_gram_error_at_line (&$1.pos, _("plural form has wrong index"));
405 $$.rhs.msgstr = string_list_concat_destroy (&$5.stringlist);
406 $$.rhs.msgstr_len = strlen ($$.rhs.msgstr) + 1;
408 $$.obsolete = $1.obsolete;
416 string_list_init (&$$.stringlist);
417 string_list_append (&$$.stringlist, $1.string);
420 $$.obsolete = $1.obsolete;
424 check_obsolete ($1, $2);
425 $$.stringlist = $1.stringlist;
426 string_list_append (&$$.stringlist, $2.string);
429 $$.obsolete = $1.obsolete;
436 string_list_init (&$$.stringlist);
437 string_list_append (&$$.stringlist, $1.string);
440 $$.obsolete = $1.obsolete;
442 | prev_string_list PREV_STRING
444 check_obsolete ($1, $2);
445 $$.stringlist = $1.stringlist;
446 string_list_append (&$$.stringlist, $2.string);
449 $$.obsolete = $1.obsolete;