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