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, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 * 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #include "gnu_msgfmt.h" 28 #include "gnu_lex.h" 29 30 static int plural_index; 31 32 %} 33 34 %union { 35 char *str; 36 int num; 37 struct entry msg; 38 struct ch c; 39 } 40 41 %token <num> DOMAIN 42 %token <num> MSGID 43 %token <num> MSGID_PLURAL 44 %token <num> MSGSTR 45 %token <num> NUM 46 %token <str> STR 47 %token <str> COMMENT 48 %token <str> SYMBOL 49 %token <c> CHR 50 %type <msg> message_string plural_messages plural_message 51 %% 52 53 start : 54 | start po 55 ; 56 57 po : comment 58 | domain 59 | body 60 ; 61 62 domain : DOMAIN STR 63 { 64 handle_domain($2); 65 } 66 ; 67 68 comment : COMMENT 69 { 70 handle_comment($1); 71 } 72 73 body : MSGID message_string MSGSTR message_string 74 { 75 struct entry och1, och2; 76 77 och1.no = 1; 78 och1.num = $1; 79 och1.str = $2.str; 80 och1.len = $2.len; 81 och1.pos = NULL; 82 83 och2.no = 1; 84 och2.num = $3; 85 och2.str = $4.str; 86 och2.len = $4.len; 87 och2.pos = NULL; 88 89 handle_message(&och1, &och2); 90 clear_state(); 91 } 92 | MSGID message_string MSGID_PLURAL 93 message_string {plural_index = 0;} plural_messages 94 { 95 size_t len; 96 struct entry och1, och2; 97 struct loc *pos1; 98 char *id_str; 99 100 len = $2.len + $4.len; 101 id_str = (char *)Xmalloc(len); 102 (void) memcpy(id_str, $2.str, $2.len); 103 (void) memcpy(id_str + $2.len, $4.str, $4.len); 104 free($2.str); 105 free($4.str); 106 107 pos1 = (struct loc *)Xmalloc(2 * sizeof (struct loc)); 108 pos1[0].off = 0; 109 pos1[0].len = $2.len; 110 pos1[0].num = $1; 111 pos1[1].off = $2.len; 112 pos1[1].len = $4.len; 113 pos1[1].num = $3; 114 och1.no = 2; 115 och1.num = $1; 116 och1.str = id_str; 117 och1.len = len; 118 och1.pos = pos1; 119 120 och2 = $6; 121 handle_message(&och1, &och2); 122 clear_state(); 123 } 124 | MSGID message_string 125 { 126 error(gettext(ERR_NO_MSGSTR), $1, cur_po); 127 /* NOTREACHED */ 128 } 129 | MSGID message_string MSGID_PLURAL message_string 130 { 131 error(gettext(ERR_NO_MSGSTRS), $1, cur_po); 132 /* NOTRECHED */ 133 } 134 | MSGID message_string plural_messages 135 { 136 error(gettext(ERR_NO_MSGID_PLURAL), $1, cur_po); 137 /* NOTREACHED */ 138 } 139 ; 140 141 message_string : STR 142 { 143 $$.str = $1; 144 $$.len = strlen($1) + 1; 145 } 146 | message_string STR 147 { 148 size_t len, len1, len2; 149 char *str; 150 151 /* $1.len includes null-termination */ 152 len1 = $1.len - 1; 153 len2 = strlen($2); 154 155 /* len doesn't include null-termination */ 156 len = len1 + len2; 157 158 str = (char *)Xmalloc(len + 1); 159 (void) memcpy(str, $1.str, len1); 160 (void) memcpy(str + len1, $2, len2 + 1); 161 free($1.str); 162 free($2); 163 $$.str = str; 164 $$.len = len + 1; 165 } 166 ; 167 168 plural_messages : plural_message 169 { 170 $$ = $1; 171 } 172 | plural_messages plural_message 173 { 174 struct loc *tmp; 175 size_t len; 176 char *plural_str; 177 int no; 178 179 no = $1.no + 1; 180 tmp = (struct loc *)Xrealloc($1.pos, 181 no * sizeof (struct loc)); 182 tmp[no - 1].off = $1.len; 183 tmp[no - 1].len = $2.len; 184 tmp[no - 1].num = $2.num; 185 free($2.pos); 186 187 len = $1.len + $2.len; 188 plural_str = (char *)Xmalloc(len); 189 (void) memcpy(plural_str, $1.str, $1.len); 190 (void) memcpy(plural_str + $1.len, $2.str, $2.len); 191 192 $$.no = no; 193 $$.num = $1.num; 194 $$.str = plural_str; 195 $$.len = len; 196 $$.pos = tmp; 197 free($1.str); 198 free($2.str); 199 } 200 ; 201 202 plural_message : MSGSTR '[' NUM ']' message_string 203 { 204 struct loc *pos; 205 if ($3 != plural_index) { 206 error(gettext(ERR_INVALID_PLURALS), $1, cur_po); 207 /* NOTREACHED */ 208 } 209 plural_index++; 210 pos = (struct loc *)Xmalloc(sizeof (struct loc)); 211 pos->off = 0; 212 pos->len = $5.len; 213 pos->num = $1; 214 $$.no = 1; 215 $$.num = $1; 216 $$.str = $5.str; 217 $$.len = $5.len; 218 $$.pos = pos; 219 } 220 ; 221 %% 222 void 223 yyerror(const char *err) 224 { 225 (void) fprintf(stderr, 226 gettext(ERR_LOCATION), cur_line, cur_po); 227 (void) fprintf(stderr, "%s\n", err); 228 229 exit(1); 230 } 231