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 *
add_qstring(char * str,char * add)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