xref: /illumos-gate/usr/src/cmd/genmsg/genmsg.y (revision e3ae4b35c024af1196582063ecee3ab79367227d)
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 (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <libintl.h>
29 #include <limits.h>
30 #include "genmsg.h"
31 extern int is_cat_found;		/* from main.c */
32 extern int lineno;			/* genmsg.l */
33 extern int msg_line;			/* genmsg.l */
34 extern int end_of_cat;			/* from genmsg.l */
35 extern void set_linemsgid(int, int);	/* from genmsg.l */
36 extern void add_msg(int, int, char *, char *, int, int); /* from util.c */
37 extern void set_msgid(int, int);
38 extern int get_msgid(char *, int, int, char *);
39 extern void warning(char *);
40 extern void yyerror(char *);
41 
42 static void do_catgets(int, int, char *);
43 static char *add_qstring(char *, char *);
44 %}
45 
46 %union {
47 	char *str;
48 	int id;
49 }
50 
51 %token CATGETS
52 %token CONST
53 %token CATD
54 %token INT, CHAR, INC
55 %token <str> STR
56 %token <id> SETID, MSGID, DIGIT
57 %token <str> QSTR
58 
59 %type <id> cast_setid, setid, cast_msgid, msgid, cast_digit, digit
60 %type <str> catd, arg_list, arg_def, arg_func, arg_exp, str,
61 	cast_qstr, paren_qstr, qstr_list
62 
63 %left '-' '+'
64 %left '*' '/'
65 %nonassoc UMINUS
66 
67 %%
68 
69 genmsg_list:	/* empty */
70 		{
71 			if (!IsActiveMode(ReplaceMode)) {
72 				src_err(srcfile, (lineno - 1),
73 				    gettext("catgets not found"));
74 			}
75 		}
76 	|	genmsg			{ is_cat_found = TRUE; }
77 	;
78 
79 genmsg:		catgets			{ end_of_cat = TRUE; }
80 	|	genmsg catgets		{ end_of_cat = TRUE; }
81 	;
82 
83 catgets:	CATGETS '(' catd ',' cast_setid ',' cast_msgid ',' cast_qstr ')'
84 		{
85 			do_catgets($5, $7, $9); free($9);
86 		}
87 	|	error
88 	;
89 
90 catd:		'(' CATD ')' arg_list		{ $$ = $4; }
91 	|	'(' CONST CATD ')' arg_list	{ $$ = $5; }
92 	|	arg_list
93 	;
94 
95 arg_list:	arg_def
96 	|	arg_list '-' '>' arg_def
97 	|	'(' arg_list '-' '>' arg_def ')' { $$ = $2; }
98 	;
99 
100 arg_def:	arg_func
101 	|	arg_exp
102 	|	str
103 	;
104 
105 arg_func:	'(' arg_func ')'	{ $$ = $2; }
106 	|	str '(' ')'
107 	|	str '(' str ')'
108 	|	str '(' cast_digit ')'
109 	|	str '(' cast_qstr ')'	{ free($3); }
110 	;
111 
112 arg_exp:	'(' arg_exp ')'		{ $$ = $2; }
113 	|	str INC
114 	|	INC str			{ $$ = $2; }
115 	;
116 
117 str:		'(' str ')'		{ $$ = $2; }
118 	|	'*' str			{ $$ = $2; }
119 	|	STR
120 	;
121 
122 cast_setid:	'(' INT ')' setid	{ $$ = $4; }
123 	|	'(' CONST INT ')' setid	{ $$ = $5; }
124 	|	setid
125 	;
126 
127 setid:		setid '+' setid		{ $$ = $1 + $3; }
128 	|	setid '-' setid		{ $$ = $1 - $3; }
129 	|	setid '*' setid		{ $$ = $1 * $3; }
130 	|	setid '/' setid
131 		{
132 			if ($3 == 0) {
133 				yyerror(gettext("zero divide"));
134 			} else {
135 				$$ = $1 / $3;
136 			}
137 		}
138 	|	'-' setid %prec UMINUS	{ $$ = -$2; }
139 	|	'(' setid ')'		{ $$ = $2; }
140 	|	SETID
141 	;
142 
143 cast_msgid:	'(' INT ')' msgid	{ $$ = $4; }
144 	|	'(' CONST INT ')' msgid	{ $$ = $5; }
145 	|	msgid
146 	;
147 
148 msgid:		msgid '+' msgid		{ $$ = $1 + $3; }
149 	|	msgid '-' msgid		{ $$ = $1 - $3; }
150 	|	msgid '*' msgid		{ $$ = $1 * $3; }
151 	|	msgid '/' msgid
152 		{
153 			if ($3 == 0) {
154 				yyerror(gettext("zero devide"));
155 			} else {
156 				$$ = $1 / $3;
157 			}
158 		}
159 	|	'-' msgid %prec UMINUS	{ $$ = -$2; }
160 	|	'(' msgid ')'		{ $$ = $2; }
161 	|	MSGID
162 	;
163 
164 cast_digit:	'(' INT ')' digit	{ $$ = $4; }
165 	|	'(' CONST INT ')' digit	{ $$ = $5; }
166 	|	digit
167 	;
168 
169 digit:		digit '+' digit		{ $$ = $1 + $3; }
170 	|	digit '-' digit		{ $$ = $1 - $3; }
171 	|	digit '*' digit		{ $$ = $1 * $3; }
172 	|	digit '/' digit
173 		{
174 			if ($3 == 0) {
175 				yyerror(gettext("zero divide"));
176 			} else {
177 				$$ = $1 / $3;
178 			}
179 		}
180 	|	'-' digit %prec UMINUS	{ $$ = -$2; }
181 	|	'(' digit ')'		{ $$ = $2; }
182 	|	DIGIT
183 	;
184 
185 cast_qstr:	'(' CHAR '*' ')' paren_qstr		{ $$ = $5; }
186 	|	'(' CONST CHAR '*' ')' paren_qstr	{ $$ = $6; }
187 	|	paren_qstr
188 	;
189 
190 paren_qstr:	'(' qstr_list ')'	{ $$ = $2; }
191 	|	qstr_list
192 	;
193 
194 qstr_list:	QSTR
195 	|	qstr_list QSTR		{ $$ = add_qstring($1, $2); }
196 	;
197 
198 %%
199 
200 static void
201 do_catgets(int setid, int msgid, char *str)
202 {
203 	int id = msgid;
204 	if (IsActiveMode(ReplaceMode)) {
205 		return;
206 	}
207 	if (setid == 0 || setid > NL_SETMAX) {
208 		src_err(srcfile, lineno,
209 		    gettext("improper set number: %d"), setid);
210 		return;
211 	}
212 	if (IsActiveMode(ProjectMode)) {
213 		set_msgid(setid, id);
214 		add_msg(setid, id, str, srcfile, lineno, TRUE);
215 	} else if (IsActiveMode(ReverseMode)) {
216 		set_linemsgid(msg_line, NOMSGID);
217 	} else if (IsActiveMode(AutoNumMode)) {
218 		if (id == NOMSGID) {
219 			id = get_msgid(srcfile, msg_line, setid, str);
220 			set_linemsgid(msg_line, id);
221 		}
222 		if (id != NOMSGID) {
223 			set_msgid(setid, id);
224 			add_msg(setid, id, str, srcfile, lineno, FALSE);
225 		}
226 	} else if (id == NOMSGID) {
227 		warning(gettext("improper message number: -1"));
228 	} else {
229 		add_msg(setid, id, str, srcfile, lineno, FALSE);
230 	}
231 }
232 
233 static char *
234 add_qstring(char *str, char *add)
235 {
236 	int len = strlen(str) + strlen(add) + 3;
237 	/* 3 includes '\', '\n' and '\0' */
238 	char *tmp = malloc(len);
239 	if (tmp == NULL) {
240 		prg_err(gettext("fatal: out of memory"));
241 		exit(EXIT_FAILURE);
242 	}
243 	(void) snprintf(tmp, len, "%s\\\n%s", str, add);
244 	free(str);
245 	free(add);
246 	return (tmp);
247 }
248