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