PageRenderTime 90ms CodeModel.GetById 16ms RepoModel.GetById 2ms app.codeStats 0ms

/gettext-tools/src/po-gram-gen.y

#
Happy | 443 lines | 396 code | 47 blank | 0 comment | 0 complexity | 68c5a59ffc3e2a91ed72a49805604636 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-2.0, GPL-3.0
  1. /* GNU gettext - internationalization aids
  2. Copyright (C) 1995-1996, 1998, 2000-2001, 2003, 2005-2006 Free Software Foundation, Inc.
  3. This file was written by Peter Miller <pmiller@agso.gov.au>
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. %{
  15. #ifdef HAVE_CONFIG_H
  16. # include "config.h"
  17. #endif
  18. /* Specification. */
  19. #include "po-gram.h"
  20. #include <stdbool.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "str-list.h"
  25. #include "po-lex.h"
  26. #include "po-charset.h"
  27. #include "error.h"
  28. #include "xalloc.h"
  29. #include "gettext.h"
  30. #include "read-catalog-abstract.h"
  31. #define _(str) gettext (str)
  32. /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
  33. as well as gratuitiously global symbol names, so we can have multiple
  34. yacc generated parsers in the same program. Note that these are only
  35. the variables produced by yacc. If other parser generators (bison,
  36. byacc, etc) produce additional global names that conflict at link time,
  37. then those parser generators need to be fixed instead of adding those
  38. names to this list. */
  39. #define yymaxdepth po_gram_maxdepth
  40. #define yyparse po_gram_parse
  41. #define yylex po_gram_lex
  42. #define yyerror po_gram_error
  43. #define yylval po_gram_lval
  44. #define yychar po_gram_char
  45. #define yydebug po_gram_debug
  46. #define yypact po_gram_pact
  47. #define yyr1 po_gram_r1
  48. #define yyr2 po_gram_r2
  49. #define yydef po_gram_def
  50. #define yychk po_gram_chk
  51. #define yypgo po_gram_pgo
  52. #define yyact po_gram_act
  53. #define yyexca po_gram_exca
  54. #define yyerrflag po_gram_errflag
  55. #define yynerrs po_gram_nerrs
  56. #define yyps po_gram_ps
  57. #define yypv po_gram_pv
  58. #define yys po_gram_s
  59. #define yy_yys po_gram_yys
  60. #define yystate po_gram_state
  61. #define yytmp po_gram_tmp
  62. #define yyv po_gram_v
  63. #define yy_yyv po_gram_yyv
  64. #define yyval po_gram_val
  65. #define yylloc po_gram_lloc
  66. #define yyreds po_gram_reds /* With YYDEBUG defined */
  67. #define yytoks po_gram_toks /* With YYDEBUG defined */
  68. #define yylhs po_gram_yylhs
  69. #define yylen po_gram_yylen
  70. #define yydefred po_gram_yydefred
  71. #define yydgoto po_gram_yydgoto
  72. #define yysindex po_gram_yysindex
  73. #define yyrindex po_gram_yyrindex
  74. #define yygindex po_gram_yygindex
  75. #define yytable po_gram_yytable
  76. #define yycheck po_gram_yycheck
  77. static long plural_counter;
  78. #define check_obsolete(value1,value2) \
  79. if ((value1).obsolete != (value2).obsolete) \
  80. po_gram_error_at_line (&(value2).pos, _("inconsistent use of #~"));
  81. static inline void
  82. do_callback_message (char *msgctxt,
  83. char *msgid, lex_pos_ty *msgid_pos, char *msgid_plural,
  84. char *msgstr, size_t msgstr_len, lex_pos_ty *msgstr_pos,
  85. char *prev_msgctxt,
  86. char *prev_msgid, char *prev_msgid_plural,
  87. bool obsolete)
  88. {
  89. /* Test for header entry. Ignore fuzziness of the header entry. */
  90. if (msgctxt == NULL && msgid[0] == '\0' && !obsolete)
  91. po_lex_charset_set (msgstr, gram_pos.file_name);
  92. po_callback_message (msgctxt,
  93. msgid, msgid_pos, msgid_plural,
  94. msgstr, msgstr_len, msgstr_pos,
  95. prev_msgctxt, prev_msgid, prev_msgid_plural,
  96. false, obsolete);
  97. }
  98. #define free_message_intro(value) \
  99. if ((value).prev_ctxt != NULL) \
  100. free ((value).prev_ctxt); \
  101. if ((value).prev_id != NULL) \
  102. free ((value).prev_id); \
  103. if ((value).prev_id_plural != NULL) \
  104. free ((value).prev_id_plural); \
  105. if ((value).ctxt != NULL) \
  106. free ((value).ctxt);
  107. %}
  108. %token COMMENT
  109. %token DOMAIN
  110. %token JUNK
  111. %token PREV_MSGCTXT
  112. %token PREV_MSGID
  113. %token PREV_MSGID_PLURAL
  114. %token PREV_STRING
  115. %token MSGCTXT
  116. %token MSGID
  117. %token MSGID_PLURAL
  118. %token MSGSTR
  119. %token NAME
  120. %token '[' ']'
  121. %token NUMBER
  122. %token STRING
  123. %union
  124. {
  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 { char *ctxt; char *id; char *id_plural; lex_pos_ty pos; bool obsolete; } prev;
  130. struct { char *prev_ctxt; char *prev_id; char *prev_id_plural; char *ctxt; lex_pos_ty pos; bool obsolete; } message_intro;
  131. struct { struct msgstr_def rhs; lex_pos_ty pos; bool obsolete; } rhs;
  132. }
  133. %type <string> STRING PREV_STRING COMMENT NAME
  134. msg_intro prev_msg_intro msgid_pluralform prev_msgid_pluralform
  135. %type <stringlist> string_list prev_string_list
  136. %type <number> NUMBER
  137. %type <pos> DOMAIN
  138. PREV_MSGCTXT PREV_MSGID PREV_MSGID_PLURAL
  139. MSGCTXT MSGID MSGID_PLURAL MSGSTR '[' ']'
  140. %type <prev> prev
  141. %type <message_intro> message_intro
  142. %type <rhs> pluralform pluralform_list
  143. %right MSGSTR
  144. %%
  145. po_file
  146. : /* empty */
  147. | po_file comment
  148. | po_file domain
  149. | po_file message
  150. | po_file error
  151. ;
  152. comment
  153. : COMMENT
  154. {
  155. po_callback_comment_dispatcher ($1.string);
  156. }
  157. ;
  158. domain
  159. : DOMAIN STRING
  160. {
  161. po_callback_domain ($2.string);
  162. }
  163. ;
  164. message
  165. : message_intro string_list MSGSTR string_list
  166. {
  167. char *string2 = string_list_concat_destroy (&$2.stringlist);
  168. char *string4 = string_list_concat_destroy (&$4.stringlist);
  169. check_obsolete ($1, $2);
  170. check_obsolete ($1, $3);
  171. check_obsolete ($1, $4);
  172. if (!$1.obsolete || pass_obsolete_entries)
  173. do_callback_message ($1.ctxt, string2, &$1.pos, NULL,
  174. string4, strlen (string4) + 1, &$3.pos,
  175. $1.prev_ctxt,
  176. $1.prev_id, $1.prev_id_plural,
  177. $1.obsolete);
  178. else
  179. {
  180. free_message_intro ($1);
  181. free (string2);
  182. free (string4);
  183. }
  184. }
  185. | message_intro string_list msgid_pluralform pluralform_list
  186. {
  187. char *string2 = string_list_concat_destroy (&$2.stringlist);
  188. check_obsolete ($1, $2);
  189. check_obsolete ($1, $3);
  190. check_obsolete ($1, $4);
  191. if (!$1.obsolete || pass_obsolete_entries)
  192. do_callback_message ($1.ctxt, string2, &$1.pos, $3.string,
  193. $4.rhs.msgstr, $4.rhs.msgstr_len, &$4.pos,
  194. $1.prev_ctxt,
  195. $1.prev_id, $1.prev_id_plural,
  196. $1.obsolete);
  197. else
  198. {
  199. free_message_intro ($1);
  200. free (string2);
  201. free ($3.string);
  202. free ($4.rhs.msgstr);
  203. }
  204. }
  205. | message_intro string_list msgid_pluralform
  206. {
  207. check_obsolete ($1, $2);
  208. check_obsolete ($1, $3);
  209. po_gram_error_at_line (&$1.pos, _("missing `msgstr[]' section"));
  210. free_message_intro ($1);
  211. string_list_destroy (&$2.stringlist);
  212. free ($3.string);
  213. }
  214. | message_intro string_list pluralform_list
  215. {
  216. check_obsolete ($1, $2);
  217. check_obsolete ($1, $3);
  218. po_gram_error_at_line (&$1.pos, _("missing `msgid_plural' section"));
  219. free_message_intro ($1);
  220. string_list_destroy (&$2.stringlist);
  221. free ($3.rhs.msgstr);
  222. }
  223. | message_intro string_list
  224. {
  225. check_obsolete ($1, $2);
  226. po_gram_error_at_line (&$1.pos, _("missing `msgstr' section"));
  227. free_message_intro ($1);
  228. string_list_destroy (&$2.stringlist);
  229. }
  230. ;
  231. message_intro
  232. : msg_intro
  233. {
  234. $$.prev_ctxt = NULL;
  235. $$.prev_id = NULL;
  236. $$.prev_id_plural = NULL;
  237. $$.ctxt = $1.string;
  238. $$.pos = $1.pos;
  239. $$.obsolete = $1.obsolete;
  240. }
  241. | prev msg_intro
  242. {
  243. check_obsolete ($1, $2);
  244. $$.prev_ctxt = $1.ctxt;
  245. $$.prev_id = $1.id;
  246. $$.prev_id_plural = $1.id_plural;
  247. $$.ctxt = $2.string;
  248. $$.pos = $2.pos;
  249. $$.obsolete = $2.obsolete;
  250. }
  251. ;
  252. prev
  253. : prev_msg_intro prev_string_list
  254. {
  255. check_obsolete ($1, $2);
  256. $$.ctxt = $1.string;
  257. $$.id = string_list_concat_destroy (&$2.stringlist);
  258. $$.id_plural = NULL;
  259. $$.pos = $1.pos;
  260. $$.obsolete = $1.obsolete;
  261. }
  262. | prev_msg_intro prev_string_list prev_msgid_pluralform
  263. {
  264. check_obsolete ($1, $2);
  265. check_obsolete ($1, $3);
  266. $$.ctxt = $1.string;
  267. $$.id = string_list_concat_destroy (&$2.stringlist);
  268. $$.id_plural = $3.string;
  269. $$.pos = $1.pos;
  270. $$.obsolete = $1.obsolete;
  271. }
  272. ;
  273. msg_intro
  274. : MSGID
  275. {
  276. $$.string = NULL;
  277. $$.pos = $1.pos;
  278. $$.obsolete = $1.obsolete;
  279. }
  280. | MSGCTXT string_list MSGID
  281. {
  282. check_obsolete ($1, $2);
  283. check_obsolete ($1, $3);
  284. $$.string = string_list_concat_destroy (&$2.stringlist);
  285. $$.pos = $3.pos;
  286. $$.obsolete = $3.obsolete;
  287. }
  288. ;
  289. prev_msg_intro
  290. : PREV_MSGID
  291. {
  292. $$.string = NULL;
  293. $$.pos = $1.pos;
  294. $$.obsolete = $1.obsolete;
  295. }
  296. | PREV_MSGCTXT prev_string_list PREV_MSGID
  297. {
  298. check_obsolete ($1, $2);
  299. check_obsolete ($1, $3);
  300. $$.string = string_list_concat_destroy (&$2.stringlist);
  301. $$.pos = $3.pos;
  302. $$.obsolete = $3.obsolete;
  303. }
  304. ;
  305. msgid_pluralform
  306. : MSGID_PLURAL string_list
  307. {
  308. check_obsolete ($1, $2);
  309. plural_counter = 0;
  310. $$.string = string_list_concat_destroy (&$2.stringlist);
  311. $$.pos = $1.pos;
  312. $$.obsolete = $1.obsolete;
  313. }
  314. ;
  315. prev_msgid_pluralform
  316. : PREV_MSGID_PLURAL prev_string_list
  317. {
  318. check_obsolete ($1, $2);
  319. $$.string = string_list_concat_destroy (&$2.stringlist);
  320. $$.pos = $1.pos;
  321. $$.obsolete = $1.obsolete;
  322. }
  323. ;
  324. pluralform_list
  325. : pluralform
  326. {
  327. $$ = $1;
  328. }
  329. | pluralform_list pluralform
  330. {
  331. check_obsolete ($1, $2);
  332. $$.rhs.msgstr = XNMALLOC ($1.rhs.msgstr_len + $2.rhs.msgstr_len, char);
  333. memcpy ($$.rhs.msgstr, $1.rhs.msgstr, $1.rhs.msgstr_len);
  334. memcpy ($$.rhs.msgstr + $1.rhs.msgstr_len, $2.rhs.msgstr, $2.rhs.msgstr_len);
  335. $$.rhs.msgstr_len = $1.rhs.msgstr_len + $2.rhs.msgstr_len;
  336. free ($1.rhs.msgstr);
  337. free ($2.rhs.msgstr);
  338. $$.pos = $1.pos;
  339. $$.obsolete = $1.obsolete;
  340. }
  341. ;
  342. pluralform
  343. : MSGSTR '[' NUMBER ']' string_list
  344. {
  345. check_obsolete ($1, $2);
  346. check_obsolete ($1, $3);
  347. check_obsolete ($1, $4);
  348. check_obsolete ($1, $5);
  349. if ($3.number != plural_counter)
  350. {
  351. if (plural_counter == 0)
  352. po_gram_error_at_line (&$1.pos, _("first plural form has nonzero index"));
  353. else
  354. po_gram_error_at_line (&$1.pos, _("plural form has wrong index"));
  355. }
  356. plural_counter++;
  357. $$.rhs.msgstr = string_list_concat_destroy (&$5.stringlist);
  358. $$.rhs.msgstr_len = strlen ($$.rhs.msgstr) + 1;
  359. $$.pos = $1.pos;
  360. $$.obsolete = $1.obsolete;
  361. }
  362. ;
  363. string_list
  364. : STRING
  365. {
  366. string_list_init (&$$.stringlist);
  367. string_list_append (&$$.stringlist, $1.string);
  368. $$.pos = $1.pos;
  369. $$.obsolete = $1.obsolete;
  370. }
  371. | string_list STRING
  372. {
  373. check_obsolete ($1, $2);
  374. $$.stringlist = $1.stringlist;
  375. string_list_append (&$$.stringlist, $2.string);
  376. $$.pos = $1.pos;
  377. $$.obsolete = $1.obsolete;
  378. }
  379. ;
  380. prev_string_list
  381. : PREV_STRING
  382. {
  383. string_list_init (&$$.stringlist);
  384. string_list_append (&$$.stringlist, $1.string);
  385. $$.pos = $1.pos;
  386. $$.obsolete = $1.obsolete;
  387. }
  388. | prev_string_list PREV_STRING
  389. {
  390. check_obsolete ($1, $2);
  391. $$.stringlist = $1.stringlist;
  392. string_list_append (&$$.stringlist, $2.string);
  393. $$.pos = $1.pos;
  394. $$.obsolete = $1.obsolete;
  395. }
  396. ;