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 * 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