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