xref: /illumos-gate/usr/src/cmd/msgfmt/gnu_po.y (revision dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9)
1 %{
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License, Version 1.0 only
7  * (the "License").  You may not use this file except in compliance
8  * with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * Copyright (c) 2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include "gnu_msgfmt.h"
29 #include "gnu_lex.h"
30 
31 static int	plural_index;
32 
33 %}
34 
35 %union {
36 	char	*str;
37 	int	num;
38 	struct entry	msg;
39 	struct ch	c;
40 }
41 
42 %token	<num> DOMAIN
43 %token	<num> MSGID
44 %token	<num> MSGID_PLURAL
45 %token	<num> MSGSTR
46 %token	<num> NUM
47 %token	<str> STR
48 %token	<str> COMMENT
49 %token	<str> SYMBOL
50 %token	<c>	CHR
51 %type	<msg> message_string plural_messages plural_message
52 %%
53 
54 start	:
55 	| start po
56 	;
57 
58 po	: comment
59 	| domain
60 	| body
61 	;
62 
63 domain	: DOMAIN STR
64 	{
65 		handle_domain($2);
66 	}
67 	;
68 
69 comment	: COMMENT
70 	{
71 		handle_comment($1);
72 	}
73 
74 body	: MSGID message_string MSGSTR message_string
75 	{
76 		struct entry	och1, och2;
77 
78 		och1.no = 1;
79 		och1.num = $1;
80 		och1.str = $2.str;
81 		och1.len = $2.len;
82 		och1.pos = NULL;
83 
84 		och2.no = 1;
85 		och2.num = $3;
86 		och2.str = $4.str;
87 		och2.len = $4.len;
88 		och2.pos = NULL;
89 
90 		handle_message(&och1, &och2);
91 		clear_state();
92 	}
93 	| MSGID message_string MSGID_PLURAL
94 		message_string {plural_index = 0;} plural_messages
95 	{
96 		size_t	len;
97 		struct entry	och1, och2;
98 		struct loc	*pos1;
99 		char	*id_str;
100 
101 		len = $2.len + $4.len;
102 		id_str = (char *)Xmalloc(len);
103 		(void) memcpy(id_str, $2.str, $2.len);
104 		(void) memcpy(id_str + $2.len, $4.str, $4.len);
105 		free($2.str);
106 		free($4.str);
107 
108 		pos1 = (struct loc *)Xmalloc(2 * sizeof (struct loc));
109 		pos1[0].off = 0;
110 		pos1[0].len = $2.len;
111 		pos1[0].num = $1;
112 		pos1[1].off = $2.len;
113 		pos1[1].len = $4.len;
114 		pos1[1].num = $3;
115 		och1.no = 2;
116 		och1.num = $1;
117 		och1.str = id_str;
118 		och1.len = len;
119 		och1.pos = pos1;
120 
121 		och2 = $6;
122 		handle_message(&och1, &och2);
123 		clear_state();
124 	}
125 	| MSGID message_string
126 	{
127 		error(gettext(ERR_NO_MSGSTR), $1, cur_po);
128 		/* NOTREACHED */
129 	}
130 	| MSGID message_string MSGID_PLURAL message_string
131 	{
132 		error(gettext(ERR_NO_MSGSTRS), $1, cur_po);
133 		/* NOTRECHED */
134 	}
135 	| MSGID message_string plural_messages
136 	{
137 		error(gettext(ERR_NO_MSGID_PLURAL), $1, cur_po);
138 		/* NOTREACHED */
139 	}
140 	;
141 
142 message_string	: STR
143 	{
144 		$$.str = $1;
145 		$$.len = strlen($1) + 1;
146 	}
147 	| message_string STR
148 	{
149 		size_t	len, len1, len2;
150 		char	*str;
151 
152 		/* $1.len includes null-termination */
153 		len1 = $1.len - 1;
154 		len2 = strlen($2);
155 
156 		/* len doesn't include null-termination */
157 		len = len1 + len2;
158 
159 		str = (char *)Xmalloc(len + 1);
160 		(void) memcpy(str, $1.str, len1);
161 		(void) memcpy(str + len1, $2, len2 + 1);
162 		free($1.str);
163 		free($2);
164 		$$.str = str;
165 		$$.len = len + 1;
166 	}
167 	;
168 
169 plural_messages	: plural_message
170 	{
171 		$$ = $1;
172 	}
173 	| plural_messages plural_message
174 	{
175 		struct loc	*tmp;
176 		size_t	len;
177 		char	*plural_str;
178 		int	no;
179 
180 		no = $1.no + 1;
181 		tmp = (struct loc *)Xrealloc($1.pos,
182 			no * sizeof (struct loc));
183 		tmp[no - 1].off = $1.len;
184 		tmp[no - 1].len = $2.len;
185 		tmp[no - 1].num = $2.num;
186 		free($2.pos);
187 
188 		len = $1.len + $2.len;
189 		plural_str = (char *)Xmalloc(len);
190 		(void) memcpy(plural_str, $1.str, $1.len);
191 		(void) memcpy(plural_str + $1.len, $2.str, $2.len);
192 
193 		$$.no = no;
194 		$$.num = $1.num;
195 		$$.str = plural_str;
196 		$$.len = len;
197 		$$.pos = tmp;
198 		free($1.str);
199 		free($2.str);
200 	}
201 	;
202 
203 plural_message	: MSGSTR '[' NUM ']' message_string
204 	{
205 		struct loc	*pos;
206 		if ($3 != plural_index) {
207 			error(gettext(ERR_INVALID_PLURALS), $1, cur_po);
208 			/* NOTREACHED */
209 		}
210 		plural_index++;
211 		pos = (struct loc *)Xmalloc(sizeof (struct loc));
212 		pos->off = 0;
213 		pos->len = $5.len;
214 		pos->num = $1;
215 		$$.no = 1;
216 		$$.num = $1;
217 		$$.str = $5.str;
218 		$$.len = $5.len;
219 		$$.pos = pos;
220 	}
221 	;
222 %%
223 void
224 yyerror(const char *err)
225 {
226 	(void) fprintf(stderr,
227 		gettext(ERR_LOCATION), cur_line, cur_po);
228 	(void) fprintf(stderr, "%s\n", err);
229 
230 	exit(1);
231 }
232