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