xref: /illumos-gate/usr/src/cmd/genmsg/genmsg.y (revision 6e54a631)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <libintl.h>
31 #include <limits.h>
32 #include "genmsg.h"
33 extern int is_cat_found;		/* from main.c */
34 extern int lineno;			/* genmsg.l */
35 extern int msg_line;			/* genmsg.l */
36 extern int end_of_cat;			/* from genmsg.l */
37 extern void set_linemsgid(int, int);	/* from genmsg.l */
38 extern void add_msg(int, int, char *, char *, int, int); /* from util.c */
39 extern void set_msgid(int, int);
40 extern int get_msgid(char *, int, int, char *);
41 extern void warning(char *);
42 extern void yyerror(char *);
43 
44 static void do_catgets(int, int, char *);
45 static char *add_qstring(char *, char *);
46 %}
47 
48 %union {
49 	char *str;
50 	int id;
51 }
52 
53 %token CATGETS
54 %token CONST
55 %token CATD
56 %token INT, CHAR, INC
57 %token <str> STR
58 %token <id> SETID, MSGID, DIGIT
59 %token <str> QSTR
60 
61 %type <id> cast_setid, setid, cast_msgid, msgid, cast_digit, digit
62 %type <str> catd, arg_list, arg_def, arg_func, arg_exp, str,
63 	cast_qstr, paren_qstr, qstr_list
64 
65 %left '-' '+'
66 %left '*' '/'
67 %nonassoc UMINUS
68 
69 %%
70 
71 genmsg_list:	/* empty */
72 		{
73 			if (!IsActiveMode(ReplaceMode)) {
74 				src_err(srcfile, (lineno - 1),
75 				    gettext("catgets not found"));
76 			}
77 		}
78 	|	genmsg			{ is_cat_found = TRUE; }
79 	;
80 
81 genmsg:		catgets			{ end_of_cat = TRUE; }
82 	|	genmsg catgets		{ end_of_cat = TRUE; }
83 	;
84 
85 catgets:	CATGETS '(' catd ',' cast_setid ',' cast_msgid ',' cast_qstr ')'
86 		{
87 			do_catgets($5, $7, $9); free($9);
88 		}
89 	|	error
90 	;
91 
92 catd:		'(' CATD ')' arg_list		{ $$ = $4; }
93 	|	'(' CONST CATD ')' arg_list	{ $$ = $5; }
94 	|	arg_list
95 	;
96 
97 arg_list:	arg_def
98 	|	arg_list '-' '>' arg_def
99 	|	'(' arg_list '-' '>' arg_def ')' { $$ = $2; }
100 	;
101 
102 arg_def:	arg_func
103 	|	arg_exp
104 	|	str
105 	;
106 
107 arg_func:	'(' arg_func ')'	{ $$ = $2; }
108 	|	str '(' ')'
109 	|	str '(' str ')'
110 	|	str '(' cast_digit ')'
111 	|	str '(' cast_qstr ')'	{ free($3); }
112 	;
113 
114 arg_exp:	'(' arg_exp ')'		{ $$ = $2; }
115 	|	str INC
116 	|	INC str			{ $$ = $2; }
117 	;
118 
119 str:		'(' str ')'		{ $$ = $2; }
120 	|	'*' str			{ $$ = $2; }
121 	|	STR
122 	;
123 
124 cast_setid:	'(' INT ')' setid	{ $$ = $4; }
125 	|	'(' CONST INT ')' setid	{ $$ = $5; }
126 	|	setid
127 	;
128 
129 setid:		setid '+' setid		{ $$ = $1 + $3; }
130 	|	setid '-' setid		{ $$ = $1 - $3; }
131 	|	setid '*' setid		{ $$ = $1 * $3; }
132 	|	setid '/' setid
133 		{
134 			if ($3 == 0) {
135 				yyerror(gettext("zero divide"));
136 			} else {
137 				$$ = $1 / $3;
138 			}
139 		}
140 	|	'-' setid %prec UMINUS	{ $$ = -$2; }
141 	|	'(' setid ')'		{ $$ = $2; }
142 	|	SETID
143 	;
144 
145 cast_msgid:	'(' INT ')' msgid	{ $$ = $4; }
146 	|	'(' CONST INT ')' msgid	{ $$ = $5; }
147 	|	msgid
148 	;
149 
150 msgid:		msgid '+' msgid		{ $$ = $1 + $3; }
151 	|	msgid '-' msgid		{ $$ = $1 - $3; }
152 	|	msgid '*' msgid		{ $$ = $1 * $3; }
153 	|	msgid '/' msgid
154 		{
155 			if ($3 == 0) {
156 				yyerror(gettext("zero devide"));
157 			} else {
158 				$$ = $1 / $3;
159 			}
160 		}
161 	|	'-' msgid %prec UMINUS	{ $$ = -$2; }
162 	|	'(' msgid ')'		{ $$ = $2; }
163 	|	MSGID
164 	;
165 
166 cast_digit:	'(' INT ')' digit	{ $$ = $4; }
167 	|	'(' CONST INT ')' digit	{ $$ = $5; }
168 	|	digit
169 	;
170 
171 digit:		digit '+' digit		{ $$ = $1 + $3; }
172 	|	digit '-' digit		{ $$ = $1 - $3; }
173 	|	digit '*' digit		{ $$ = $1 * $3; }
174 	|	digit '/' digit
175 		{
176 			if ($3 == 0) {
177 				yyerror(gettext("zero divide"));
178 			} else {
179 				$$ = $1 / $3;
180 			}
181 		}
182 	|	'-' digit %prec UMINUS	{ $$ = -$2; }
183 	|	'(' digit ')'		{ $$ = $2; }
184 	|	DIGIT
185 	;
186 
187 cast_qstr:	'(' CHAR '*' ')' paren_qstr		{ $$ = $5; }
188 	|	'(' CONST CHAR '*' ')' paren_qstr	{ $$ = $6; }
189 	|	paren_qstr
190 	;
191 
192 paren_qstr:	'(' qstr_list ')'	{ $$ = $2; }
193 	|	qstr_list
194 	;
195 
196 qstr_list:	QSTR
197 	|	qstr_list QSTR		{ $$ = add_qstring($1, $2); }
198 	;
199 
200 %%
201 
202 static void
203 do_catgets(int setid, int msgid, char *str)
204 {
205 	int id = msgid;
206 	if (IsActiveMode(ReplaceMode)) {
207 		return;
208 	}
209 	if (setid == 0 || setid > NL_SETMAX) {
210 		src_err(srcfile, lineno,
211 		    gettext("improper set number: %d"), setid);
212 		return;
213 	}
214 	if (IsActiveMode(ProjectMode)) {
215 		set_msgid(setid, id);
216 		add_msg(setid, id, str, srcfile, lineno, TRUE);
217 	} else if (IsActiveMode(ReverseMode)) {
218 		set_linemsgid(msg_line, NOMSGID);
219 	} else if (IsActiveMode(AutoNumMode)) {
220 		if (id == NOMSGID) {
221 			id = get_msgid(srcfile, msg_line, setid, str);
222 			set_linemsgid(msg_line, id);
223 		}
224 		if (id != NOMSGID) {
225 			set_msgid(setid, id);
226 			add_msg(setid, id, str, srcfile, lineno, FALSE);
227 		}
228 	} else if (id == NOMSGID) {
229 		warning(gettext("improper message number: -1"));
230 	} else {
231 		add_msg(setid, id, str, srcfile, lineno, FALSE);
232 	}
233 }
234 
235 static char *
add_qstring(char * str,char * add)236 add_qstring(char *str, char *add)
237 {
238 	int len = strlen(str) + strlen(add) + 3;
239 	/* 3 includes '\', '\n' and '\0' */
240 	char *tmp = malloc(len);
241 	if (tmp == NULL) {
242 		prg_err(gettext("fatal: out of memory"));
243 		exit(EXIT_FAILURE);
244 	}
245 	(void) snprintf(tmp, len, "%s\\\n%s", str, add);
246 	free(str);
247 	free(add);
248 	return (tmp);
249 }
250