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
31static 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
54start	:
55	| start po
56	;
57
58po	: comment
59	| domain
60	| body
61	;
62
63domain	: DOMAIN STR
64	{
65		handle_domain($2);
66	}
67	;
68
69comment	: COMMENT
70	{
71		handle_comment($1);
72	}
73
74body	: 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
142message_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
169plural_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
203plural_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%%
223void
224yyerror(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