mcparse.y 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. %{ /* mcparse.y -- parser for Windows mc files
  2. Copyright (C) 2007-2022 Free Software Foundation, Inc.
  3. Parser for Windows mc files
  4. Written by Kai Tietz, Onevision.
  5. This file is part of GNU Binutils.
  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.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
  17. 02110-1301, USA. */
  18. /* This is a parser for Windows rc files. It is based on the parser
  19. by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */
  20. #include "sysdep.h"
  21. #include "bfd.h"
  22. #include "bucomm.h"
  23. #include "libiberty.h"
  24. #include "windmc.h"
  25. #include "safe-ctype.h"
  26. static rc_uint_type mc_last_id = 0;
  27. static rc_uint_type mc_sefa_val = 0;
  28. static unichar *mc_last_symbol = NULL;
  29. static const mc_keyword *mc_cur_severity = NULL;
  30. static const mc_keyword *mc_cur_facility = NULL;
  31. static mc_node *cur_node = NULL;
  32. %}
  33. %union
  34. {
  35. rc_uint_type ival;
  36. unichar *ustr;
  37. const mc_keyword *tok;
  38. mc_node *nod;
  39. };
  40. %start input
  41. %token NL
  42. %token<ustr> MCIDENT MCFILENAME MCLINE MCCOMMENT
  43. %token<tok> MCTOKEN
  44. %token MCENDLINE
  45. %token MCLANGUAGENAMES MCFACILITYNAMES MCSEVERITYNAMES MCOUTPUTBASE MCMESSAGEIDTYPEDEF
  46. %token MCLANGUAGE MCMESSAGEID MCSEVERITY MCFACILITY MCSYMBOLICNAME
  47. %token <ival> MCNUMBER
  48. %type<ival> id vid sefasy_def
  49. %type<ustr> alias_name token lines comments
  50. %type<tok> lang
  51. %%
  52. input: entities
  53. ;
  54. entities:
  55. /* empty */
  56. | entities entity
  57. ;
  58. entity: global_section
  59. | message
  60. | comments
  61. {
  62. cur_node = mc_add_node ();
  63. cur_node->user_text = $1;
  64. }
  65. | error { mc_fatal ("syntax error"); }
  66. ;
  67. global_section:
  68. MCSEVERITYNAMES '=' '(' severitymaps ')'
  69. | MCSEVERITYNAMES '=' '(' severitymaps error { mc_fatal ("missing ')' in SeverityNames"); }
  70. | MCSEVERITYNAMES '=' error { mc_fatal ("missing '(' in SeverityNames"); }
  71. | MCSEVERITYNAMES error { mc_fatal ("missing '=' for SeverityNames"); }
  72. | MCLANGUAGENAMES '=' '(' langmaps ')'
  73. | MCLANGUAGENAMES '=' '(' langmaps error { mc_fatal ("missing ')' in LanguageNames"); }
  74. | MCLANGUAGENAMES '=' error { mc_fatal ("missing '(' in LanguageNames"); }
  75. | MCLANGUAGENAMES error { mc_fatal ("missing '=' for LanguageNames"); }
  76. | MCFACILITYNAMES '=' '(' facilitymaps ')'
  77. | MCFACILITYNAMES '=' '(' facilitymaps error { mc_fatal ("missing ')' in FacilityNames"); }
  78. | MCFACILITYNAMES '=' error { mc_fatal ("missing '(' in FacilityNames"); }
  79. | MCFACILITYNAMES error { mc_fatal ("missing '=' for FacilityNames"); }
  80. | MCOUTPUTBASE '=' MCNUMBER
  81. {
  82. if ($3 != 10 && $3 != 16)
  83. mc_fatal ("OutputBase allows 10 or 16 as value");
  84. mcset_out_values_are_decimal = ($3 == 10 ? 1 : 0);
  85. }
  86. | MCMESSAGEIDTYPEDEF '=' MCIDENT
  87. {
  88. mcset_msg_id_typedef = $3;
  89. }
  90. | MCMESSAGEIDTYPEDEF '=' error
  91. {
  92. mc_fatal ("MessageIdTypedef expects an identifier");
  93. }
  94. | MCMESSAGEIDTYPEDEF error
  95. {
  96. mc_fatal ("missing '=' for MessageIdTypedef");
  97. }
  98. ;
  99. severitymaps:
  100. severitymap
  101. | severitymaps severitymap
  102. | error { mc_fatal ("severity ident missing"); }
  103. ;
  104. severitymap:
  105. token '=' MCNUMBER alias_name
  106. {
  107. mc_add_keyword ($1, MCTOKEN, "severity", $3, $4);
  108. }
  109. | token '=' error { mc_fatal ("severity number missing"); }
  110. | token error { mc_fatal ("severity missing '='"); }
  111. ;
  112. facilitymaps:
  113. facilitymap
  114. | facilitymaps facilitymap
  115. | error { mc_fatal ("missing ident in FacilityNames"); }
  116. ;
  117. facilitymap:
  118. token '=' MCNUMBER alias_name
  119. {
  120. mc_add_keyword ($1, MCTOKEN, "facility", $3, $4);
  121. }
  122. | token '=' error { mc_fatal ("facility number missing"); }
  123. | token error { mc_fatal ("facility missing '='"); }
  124. ;
  125. langmaps:
  126. langmap
  127. | langmaps langmap
  128. | error { mc_fatal ("missing ident in LanguageNames"); }
  129. ;
  130. langmap:
  131. token '=' MCNUMBER lex_want_filename ':' MCFILENAME
  132. {
  133. mc_add_keyword ($1, MCTOKEN, "language", $3, $6);
  134. }
  135. | token '=' MCNUMBER lex_want_filename ':' error { mc_fatal ("missing filename in LanguageNames"); }
  136. | token '=' MCNUMBER error { mc_fatal ("missing ':' in LanguageNames"); }
  137. | token '=' error { mc_fatal ("missing language code in LanguageNames"); }
  138. | token error { mc_fatal ("missing '=' for LanguageNames"); }
  139. ;
  140. alias_name:
  141. /* empty */
  142. {
  143. $$ = NULL;
  144. }
  145. | ':' MCIDENT
  146. {
  147. $$ = $2;
  148. }
  149. | ':' error { mc_fatal ("illegal token in identifier"); $$ = NULL; }
  150. ;
  151. message:
  152. id sefasy_def
  153. {
  154. cur_node = mc_add_node ();
  155. cur_node->symbol = mc_last_symbol;
  156. cur_node->facility = mc_cur_facility;
  157. cur_node->severity = mc_cur_severity;
  158. cur_node->id = ($1 & 0xffffUL);
  159. cur_node->vid = ($1 & 0xffffUL) | mc_sefa_val;
  160. cur_node->id_typecast = mcset_msg_id_typedef;
  161. mc_last_id = $1;
  162. }
  163. lang_entities
  164. ;
  165. id: MCMESSAGEID '=' vid { $$ = $3; }
  166. | MCMESSAGEID '=' error { mc_fatal ("missing number in MessageId"); $$ = 0; }
  167. | MCMESSAGEID error { mc_fatal ("missing '=' for MessageId"); $$ = 0; }
  168. ;
  169. vid: /* empty */
  170. {
  171. $$ = ++mc_last_id;
  172. }
  173. | MCNUMBER
  174. {
  175. $$ = $1;
  176. }
  177. | '+' MCNUMBER
  178. {
  179. $$ = mc_last_id + $2;
  180. }
  181. | '+' error { mc_fatal ("missing number after MessageId '+'"); }
  182. ;
  183. sefasy_def:
  184. /* empty */
  185. {
  186. $$ = 0;
  187. mc_sefa_val = (mcset_custom_bit ? 1 : 0) << 29;
  188. mc_last_symbol = NULL;
  189. mc_cur_severity = NULL;
  190. mc_cur_facility = NULL;
  191. }
  192. | sefasy_def severity
  193. {
  194. if ($1 & 1)
  195. mc_warn (_("duplicate definition of Severity"));
  196. $$ = $1 | 1;
  197. }
  198. | sefasy_def facility
  199. {
  200. if ($1 & 2)
  201. mc_warn (_("duplicate definition of Facility"));
  202. $$ = $1 | 2;
  203. }
  204. | sefasy_def symbol
  205. {
  206. if ($1 & 4)
  207. mc_warn (_("duplicate definition of SymbolicName"));
  208. $$ = $1 | 4;
  209. }
  210. ;
  211. severity: MCSEVERITY '=' MCTOKEN
  212. {
  213. mc_sefa_val &= ~ (0x3UL << 30);
  214. mc_sefa_val |= (($3->nval & 0x3UL) << 30);
  215. mc_cur_severity = $3;
  216. }
  217. ;
  218. facility: MCFACILITY '=' MCTOKEN
  219. {
  220. mc_sefa_val &= ~ (0xfffUL << 16);
  221. mc_sefa_val |= (($3->nval & 0xfffUL) << 16);
  222. mc_cur_facility = $3;
  223. }
  224. ;
  225. symbol: MCSYMBOLICNAME '=' MCIDENT
  226. {
  227. mc_last_symbol = $3;
  228. }
  229. ;
  230. lang_entities:
  231. lang_entity
  232. | lang_entities lang_entity
  233. ;
  234. lang_entity:
  235. lang lex_want_line lines MCENDLINE
  236. {
  237. mc_node_lang *h;
  238. h = mc_add_node_lang (cur_node, $1, cur_node->vid);
  239. h->message = $3;
  240. if (mcset_max_message_length != 0 && unichar_len (h->message) > mcset_max_message_length)
  241. mc_warn ("message length to long");
  242. }
  243. ;
  244. lines: MCLINE
  245. {
  246. $$ = $1;
  247. }
  248. | lines MCLINE
  249. {
  250. unichar *h;
  251. rc_uint_type l1,l2;
  252. l1 = unichar_len ($1);
  253. l2 = unichar_len ($2);
  254. h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
  255. if (l1) memcpy (h, $1, l1 * sizeof (unichar));
  256. if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar));
  257. h[l1 + l2] = 0;
  258. $$ = h;
  259. }
  260. | error { mc_fatal ("missing end of message text"); $$ = NULL; }
  261. | lines error { mc_fatal ("missing end of message text"); $$ = $1; }
  262. ;
  263. comments: MCCOMMENT { $$ = $1; }
  264. | comments MCCOMMENT
  265. {
  266. unichar *h;
  267. rc_uint_type l1,l2;
  268. l1 = unichar_len ($1);
  269. l2 = unichar_len ($2);
  270. h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
  271. if (l1) memcpy (h, $1, l1 * sizeof (unichar));
  272. if (l2) memcpy (&h[l1], $2, l2 * sizeof (unichar));
  273. h[l1 + l2] = 0;
  274. $$ = h;
  275. }
  276. ;
  277. lang: MCLANGUAGE lex_want_nl '=' MCTOKEN NL
  278. {
  279. $$ = $4;
  280. }
  281. | MCLANGUAGE lex_want_nl '=' MCIDENT NL
  282. {
  283. $$ = NULL;
  284. mc_fatal (_("undeclared language identifier"));
  285. }
  286. | MCLANGUAGE lex_want_nl '=' token error
  287. {
  288. $$ = NULL;
  289. mc_fatal ("missing newline after Language");
  290. }
  291. | MCLANGUAGE lex_want_nl '=' error
  292. {
  293. $$ = NULL;
  294. mc_fatal ("missing ident for Language");
  295. }
  296. | MCLANGUAGE error
  297. {
  298. $$ = NULL;
  299. mc_fatal ("missing '=' for Language");
  300. }
  301. ;
  302. token: MCIDENT { $$ = $1; }
  303. | MCTOKEN { $$ = $1->usz; }
  304. ;
  305. lex_want_nl:
  306. /* Empty */ { mclex_want_nl = 1; }
  307. ;
  308. lex_want_line:
  309. /* Empty */ { mclex_want_line = 1; }
  310. ;
  311. lex_want_filename:
  312. /* Empty */ { mclex_want_filename = 1; }
  313. ;
  314. %%
  315. /* Something else. */