1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "gnu_msgfmt.h" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate static int next_entry_is_fuzzy = 0; 32*7c478bd9Sstevel@tonic-gate static int next_entry_is_c_format = 0; 33*7c478bd9Sstevel@tonic-gate static struct catalog *cur_catalog = NULL; 34*7c478bd9Sstevel@tonic-gate static char *cur_mo = NULL; 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate FILE *fp; 37*7c478bd9Sstevel@tonic-gate iconv_t cd = (iconv_t)-1; 38*7c478bd9Sstevel@tonic-gate struct catalog *catalog_head = NULL; 39*7c478bd9Sstevel@tonic-gate int cur_po_index = 0; 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate static size_t 42*7c478bd9Sstevel@tonic-gate search_alias(char **paddr, size_t size, const char *variant) 43*7c478bd9Sstevel@tonic-gate { 44*7c478bd9Sstevel@tonic-gate char *addr = *paddr; 45*7c478bd9Sstevel@tonic-gate char *p, *sp, *q; 46*7c478bd9Sstevel@tonic-gate size_t var_len, can_len; 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate var_len = strlen(variant); 49*7c478bd9Sstevel@tonic-gate p = addr; 50*7c478bd9Sstevel@tonic-gate q = addr + size; 51*7c478bd9Sstevel@tonic-gate while (q > p) { 52*7c478bd9Sstevel@tonic-gate if (*p == '#') { 53*7c478bd9Sstevel@tonic-gate /* 54*7c478bd9Sstevel@tonic-gate * Line beginning with '#' is a comment 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate p++; 57*7c478bd9Sstevel@tonic-gate while ((q > p) && (*p++ != '\n')) 58*7c478bd9Sstevel@tonic-gate ; 59*7c478bd9Sstevel@tonic-gate continue; 60*7c478bd9Sstevel@tonic-gate } 61*7c478bd9Sstevel@tonic-gate /* skip leading spaces */ 62*7c478bd9Sstevel@tonic-gate while ((q > p) && 63*7c478bd9Sstevel@tonic-gate ((*p == ' ') || (*p == '\t'))) 64*7c478bd9Sstevel@tonic-gate p++; 65*7c478bd9Sstevel@tonic-gate if (q <= p) 66*7c478bd9Sstevel@tonic-gate break; 67*7c478bd9Sstevel@tonic-gate sp = p; 68*7c478bd9Sstevel@tonic-gate while ((q > p) && (*p != ' ') && 69*7c478bd9Sstevel@tonic-gate (*p != '\t') && (*p != '\n')) 70*7c478bd9Sstevel@tonic-gate p++; 71*7c478bd9Sstevel@tonic-gate if (q <= p) { 72*7c478bd9Sstevel@tonic-gate /* invalid entry */ 73*7c478bd9Sstevel@tonic-gate break; 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate if (*p == '\n') { 76*7c478bd9Sstevel@tonic-gate /* invalid entry */ 77*7c478bd9Sstevel@tonic-gate p++; 78*7c478bd9Sstevel@tonic-gate continue; 79*7c478bd9Sstevel@tonic-gate } 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate if (((p - sp) != var_len) || 82*7c478bd9Sstevel@tonic-gate ((strncmp(sp, variant, var_len) != 0) && 83*7c478bd9Sstevel@tonic-gate (strncasecmp(sp, variant, var_len) != 0))) { 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * didn't match 86*7c478bd9Sstevel@tonic-gate */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate /* skip remaining chars in this line */ 89*7c478bd9Sstevel@tonic-gate p++; 90*7c478bd9Sstevel@tonic-gate while ((q > p) && (*p++ != '\n')) 91*7c478bd9Sstevel@tonic-gate ; 92*7c478bd9Sstevel@tonic-gate continue; 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* matching entry found */ 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* skip spaces */ 98*7c478bd9Sstevel@tonic-gate while ((q > p) && 99*7c478bd9Sstevel@tonic-gate ((*p == ' ') || (*p == '\t'))) 100*7c478bd9Sstevel@tonic-gate p++; 101*7c478bd9Sstevel@tonic-gate if (q <= p) 102*7c478bd9Sstevel@tonic-gate break; 103*7c478bd9Sstevel@tonic-gate sp = p; 104*7c478bd9Sstevel@tonic-gate while ((q > p) && (*p != ' ') && 105*7c478bd9Sstevel@tonic-gate (*p != '\t') && (*p != '\n')) 106*7c478bd9Sstevel@tonic-gate p++; 107*7c478bd9Sstevel@tonic-gate can_len = p - sp; 108*7c478bd9Sstevel@tonic-gate if (can_len == 0) { 109*7c478bd9Sstevel@tonic-gate while ((q > p) && (*p++ != '\n')) 110*7c478bd9Sstevel@tonic-gate ; 111*7c478bd9Sstevel@tonic-gate continue; 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate *paddr = sp; 114*7c478bd9Sstevel@tonic-gate return (can_len); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate return (0); 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * Checks if the specified charset is equivalent to UTF-8. 121*7c478bd9Sstevel@tonic-gate * If it's equivalent to UTF-8, returns 1; Otherwise, returns 0. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate static int 124*7c478bd9Sstevel@tonic-gate check_utf8(const char *charset) 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate int fd; 127*7c478bd9Sstevel@tonic-gate struct stat64 statbuf; 128*7c478bd9Sstevel@tonic-gate caddr_t addr; 129*7c478bd9Sstevel@tonic-gate size_t buflen, charset_len, utf8_len; 130*7c478bd9Sstevel@tonic-gate char *c_charset, *c_utf8, *p; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate if (strcmp(charset, DEST_CHARSET) == 0) 133*7c478bd9Sstevel@tonic-gate return (1); 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate fd = open(_ENCODING_ALIAS_PATH, O_RDONLY); 136*7c478bd9Sstevel@tonic-gate if (fd == -1) { 137*7c478bd9Sstevel@tonic-gate /* no alias file found */ 138*7c478bd9Sstevel@tonic-gate return (0); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate if (fstat64(fd, &statbuf) == -1) { 141*7c478bd9Sstevel@tonic-gate (void) close(fd); 142*7c478bd9Sstevel@tonic-gate return (0); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate buflen = (size_t)statbuf.st_size; 145*7c478bd9Sstevel@tonic-gate addr = mmap(NULL, buflen, PROT_READ, MAP_SHARED, fd, 0); 146*7c478bd9Sstevel@tonic-gate (void) close(fd); 147*7c478bd9Sstevel@tonic-gate if (addr == MAP_FAILED) { 148*7c478bd9Sstevel@tonic-gate warning("mmap() for %s failed.", _ENCODING_ALIAS_PATH); 149*7c478bd9Sstevel@tonic-gate return (0); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate p = (char *)addr; 152*7c478bd9Sstevel@tonic-gate charset_len = search_alias(&p, buflen, charset); 153*7c478bd9Sstevel@tonic-gate if (charset_len) { 154*7c478bd9Sstevel@tonic-gate c_charset = alloca(charset_len + 1); 155*7c478bd9Sstevel@tonic-gate (void) memcpy(c_charset, p, charset_len); 156*7c478bd9Sstevel@tonic-gate c_charset[charset_len] = '\0'; 157*7c478bd9Sstevel@tonic-gate } else { 158*7c478bd9Sstevel@tonic-gate c_charset = (char *)charset; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate p = (char *)addr; 161*7c478bd9Sstevel@tonic-gate utf8_len = search_alias(&p, buflen, DEST_CHARSET); 162*7c478bd9Sstevel@tonic-gate if (utf8_len) { 163*7c478bd9Sstevel@tonic-gate c_utf8 = alloca(utf8_len + 1); 164*7c478bd9Sstevel@tonic-gate (void) memcpy(c_utf8, p, utf8_len); 165*7c478bd9Sstevel@tonic-gate c_utf8[utf8_len] = '\0'; 166*7c478bd9Sstevel@tonic-gate } else { 167*7c478bd9Sstevel@tonic-gate c_utf8 = DEST_CHARSET; 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate (void) munmap(addr, buflen); 170*7c478bd9Sstevel@tonic-gate if (charset_len == 0 && utf8_len == 0) { 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Entry for neither charset nor utf8 found 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate return (0); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if (strcmp(c_charset, c_utf8) == 0) 178*7c478bd9Sstevel@tonic-gate return (1); 179*7c478bd9Sstevel@tonic-gate else 180*7c478bd9Sstevel@tonic-gate return (0); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate static void 184*7c478bd9Sstevel@tonic-gate conv_init(const char *charset) 185*7c478bd9Sstevel@tonic-gate { 186*7c478bd9Sstevel@tonic-gate if (charset == NULL) { 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * No conversion 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate cd = (iconv_t)-1; 191*7c478bd9Sstevel@tonic-gate return; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate if (check_utf8(charset)) { 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * Charset is UTF-8. 196*7c478bd9Sstevel@tonic-gate * No conversion is required. 197*7c478bd9Sstevel@tonic-gate */ 198*7c478bd9Sstevel@tonic-gate cd = (iconv_t)-1; 199*7c478bd9Sstevel@tonic-gate return; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate cd = iconv_open(DEST_CHARSET, charset); 202*7c478bd9Sstevel@tonic-gate if (cd == (iconv_t)-1) { 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * No such a conversion 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_NOCONV), 207*7c478bd9Sstevel@tonic-gate cur_line, cur_po, charset, DEST_CHARSET); 208*7c478bd9Sstevel@tonic-gate return; 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate void 213*7c478bd9Sstevel@tonic-gate clear_state(void) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate next_entry_is_fuzzy = 0; 216*7c478bd9Sstevel@tonic-gate next_entry_is_c_format = 0; 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate void 220*7c478bd9Sstevel@tonic-gate handle_domain(char *domainname) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate if (outfile) { 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * outfile has been specified by -o option 225*7c478bd9Sstevel@tonic-gate * ignore all domain directives 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate if (verbose_flag) { 228*7c478bd9Sstevel@tonic-gate diag(gettext(DIAG_IGNORE_DOMAIN), 229*7c478bd9Sstevel@tonic-gate cur_line, cur_po, domainname); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate free(domainname); 232*7c478bd9Sstevel@tonic-gate return; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (strict_flag) { 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * add ".mo" to the domain 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate char *tmp; 240*7c478bd9Sstevel@tonic-gate tmp = Xrealloc(domainname, strlen(domainname) + 3 + 1); 241*7c478bd9Sstevel@tonic-gate (void) strcat(tmp, ".mo"); 242*7c478bd9Sstevel@tonic-gate domainname = tmp; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate catalog_init(domainname); 245*7c478bd9Sstevel@tonic-gate free(domainname); 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate void 249*7c478bd9Sstevel@tonic-gate catalog_init(const char *filename) 250*7c478bd9Sstevel@tonic-gate { 251*7c478bd9Sstevel@tonic-gate struct catalog *p; 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate if (!catalog_head) { 254*7c478bd9Sstevel@tonic-gate p = Xcalloc(1, sizeof (struct catalog)); 255*7c478bd9Sstevel@tonic-gate p->fname = Xstrdup(filename); 256*7c478bd9Sstevel@tonic-gate p->msg_size = DEF_MSG_NUM; 257*7c478bd9Sstevel@tonic-gate p->nmsg = 0; 258*7c478bd9Sstevel@tonic-gate p->msg = Xcalloc(p->msg_size, sizeof (struct messages)); 259*7c478bd9Sstevel@tonic-gate p->thash_size = find_prime(DEF_MSG_NUM); 260*7c478bd9Sstevel@tonic-gate p->thash = Xcalloc(p->thash_size, sizeof (unsigned int)); 261*7c478bd9Sstevel@tonic-gate catalog_head = p; 262*7c478bd9Sstevel@tonic-gate } else { 263*7c478bd9Sstevel@tonic-gate p = catalog_head; 264*7c478bd9Sstevel@tonic-gate for (; ; ) { 265*7c478bd9Sstevel@tonic-gate struct catalog *tmp; 266*7c478bd9Sstevel@tonic-gate if (strcmp(p->fname, filename) == 0) { 267*7c478bd9Sstevel@tonic-gate /* already registered */ 268*7c478bd9Sstevel@tonic-gate break; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate if (p->next) { 271*7c478bd9Sstevel@tonic-gate p = p->next; 272*7c478bd9Sstevel@tonic-gate continue; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * this domain hasn't been registered 276*7c478bd9Sstevel@tonic-gate */ 277*7c478bd9Sstevel@tonic-gate tmp = Xcalloc(1, sizeof (struct catalog)); 278*7c478bd9Sstevel@tonic-gate tmp->fname = Xstrdup(filename); 279*7c478bd9Sstevel@tonic-gate tmp->msg_size = DEF_MSG_NUM; 280*7c478bd9Sstevel@tonic-gate tmp->nmsg = 0; 281*7c478bd9Sstevel@tonic-gate tmp->msg = Xcalloc(tmp->msg_size, 282*7c478bd9Sstevel@tonic-gate sizeof (struct messages)); 283*7c478bd9Sstevel@tonic-gate tmp->thash_size = find_prime(DEF_MSG_NUM); 284*7c478bd9Sstevel@tonic-gate tmp->thash = Xcalloc(tmp->thash_size, 285*7c478bd9Sstevel@tonic-gate sizeof (unsigned int)); 286*7c478bd9Sstevel@tonic-gate p->next = tmp; 287*7c478bd9Sstevel@tonic-gate p = tmp; 288*7c478bd9Sstevel@tonic-gate break; 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate cur_catalog = p; 292*7c478bd9Sstevel@tonic-gate cur_mo = p->fname; 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate void 297*7c478bd9Sstevel@tonic-gate handle_comment(char *comment) 298*7c478bd9Sstevel@tonic-gate { 299*7c478bd9Sstevel@tonic-gate char *p; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate p = comment; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (*p != ',') { 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * This comment is just informative only. 306*7c478bd9Sstevel@tonic-gate */ 307*7c478bd9Sstevel@tonic-gate free(comment); 308*7c478bd9Sstevel@tonic-gate return; 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * Checks "fuzzy", "c-format", and "no-c-format" 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate p++; 314*7c478bd9Sstevel@tonic-gate if (strstr(p, "fuzzy") != NULL) { 315*7c478bd9Sstevel@tonic-gate next_entry_is_fuzzy = 1; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate if (strstr(p, "no-c-format") != NULL) { 318*7c478bd9Sstevel@tonic-gate next_entry_is_c_format = 0; 319*7c478bd9Sstevel@tonic-gate } else if (strstr(p, "c-format") != NULL) { 320*7c478bd9Sstevel@tonic-gate next_entry_is_c_format = 1; 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate free(comment); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate void 327*7c478bd9Sstevel@tonic-gate handle_message(struct entry *id, struct entry *str) 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate char *charset, *nplurals, *tmp, *p; 330*7c478bd9Sstevel@tonic-gate struct messages *msg, *dupmsg; 331*7c478bd9Sstevel@tonic-gate size_t len; 332*7c478bd9Sstevel@tonic-gate unsigned int hash_val; 333*7c478bd9Sstevel@tonic-gate unsigned int nmsg, n, thash_idx; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if (cur_mo == NULL) { 336*7c478bd9Sstevel@tonic-gate /* 337*7c478bd9Sstevel@tonic-gate * output file hasn't been specified, nor 338*7c478bd9Sstevel@tonic-gate * no domain directive found 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate char *default_domain; 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate default_domain = strict_flag ? DEFAULT_DOMAIN_MO : 343*7c478bd9Sstevel@tonic-gate DEFAULT_DOMAIN; 344*7c478bd9Sstevel@tonic-gate catalog_init(default_domain); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * cur_catalog should be valid, at this point 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate hash_val = hashpjw(id->str); 352*7c478bd9Sstevel@tonic-gate dupmsg = search_msg(cur_catalog, id->str, hash_val); 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate if (dupmsg) { 355*7c478bd9Sstevel@tonic-gate if ((dupmsg->str_len == str->len) && 356*7c478bd9Sstevel@tonic-gate (memcmp(dupmsg->str, str->str, str->len) == 0)) { 357*7c478bd9Sstevel@tonic-gate /* totally same entry */ 358*7c478bd9Sstevel@tonic-gate if (verbose_flag) { 359*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_DUP_ENTRIES), 360*7c478bd9Sstevel@tonic-gate dupmsg->num, po_names[dupmsg->po], 361*7c478bd9Sstevel@tonic-gate id->num, cur_po); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate free(id->str); 364*7c478bd9Sstevel@tonic-gate if (id->pos) 365*7c478bd9Sstevel@tonic-gate free(id->pos); 366*7c478bd9Sstevel@tonic-gate free(str->str); 367*7c478bd9Sstevel@tonic-gate if (str->pos) 368*7c478bd9Sstevel@tonic-gate free(str->pos); 369*7c478bd9Sstevel@tonic-gate return; 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate /* duplicate msgid */ 372*7c478bd9Sstevel@tonic-gate if (verbose_flag) { 373*7c478bd9Sstevel@tonic-gate diag(gettext(ERR_DUP_ENTRIES), 374*7c478bd9Sstevel@tonic-gate dupmsg->num, po_names[dupmsg->po], 375*7c478bd9Sstevel@tonic-gate id->num, cur_po); 376*7c478bd9Sstevel@tonic-gate po_error++; 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate /* ignore this etnry */ 379*7c478bd9Sstevel@tonic-gate free(id->str); 380*7c478bd9Sstevel@tonic-gate if (id->pos) 381*7c478bd9Sstevel@tonic-gate free(id->pos); 382*7c478bd9Sstevel@tonic-gate free(str->str); 383*7c478bd9Sstevel@tonic-gate if (str->pos) 384*7c478bd9Sstevel@tonic-gate free(str->pos); 385*7c478bd9Sstevel@tonic-gate return; 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate if (next_entry_is_fuzzy) { 389*7c478bd9Sstevel@tonic-gate /* fuzzy entry */ 390*7c478bd9Sstevel@tonic-gate cur_catalog->fnum++; 391*7c478bd9Sstevel@tonic-gate if (!fuzzy_flag) { 392*7c478bd9Sstevel@tonic-gate /* ignore this entry */ 393*7c478bd9Sstevel@tonic-gate free(id->str); 394*7c478bd9Sstevel@tonic-gate if (id->pos) 395*7c478bd9Sstevel@tonic-gate free(id->pos); 396*7c478bd9Sstevel@tonic-gate free(str->str); 397*7c478bd9Sstevel@tonic-gate if (str->pos) 398*7c478bd9Sstevel@tonic-gate free(str->pos); 399*7c478bd9Sstevel@tonic-gate return; 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate if (str->len == str->no) { 404*7c478bd9Sstevel@tonic-gate /* this entry is not translated */ 405*7c478bd9Sstevel@tonic-gate cur_catalog->unum++; 406*7c478bd9Sstevel@tonic-gate free(id->str); 407*7c478bd9Sstevel@tonic-gate if (id->pos) 408*7c478bd9Sstevel@tonic-gate free(id->pos); 409*7c478bd9Sstevel@tonic-gate free(str->str); 410*7c478bd9Sstevel@tonic-gate if (str->pos) 411*7c478bd9Sstevel@tonic-gate free(str->pos); 412*7c478bd9Sstevel@tonic-gate return; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate /* Checks if this is the header entry */ 416*7c478bd9Sstevel@tonic-gate if ((id->no == 1) && (id->len == 1)) { 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * Header entry 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate cur_catalog->header++; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * Need to extract the charset information 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate charset = strstr(str->str, CHARSET_STR); 426*7c478bd9Sstevel@tonic-gate if (charset == NULL) { 427*7c478bd9Sstevel@tonic-gate /* no charset information */ 428*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_NOCHARSET), 429*7c478bd9Sstevel@tonic-gate id->num, cur_po, str->num); 430*7c478bd9Sstevel@tonic-gate conv_init(NULL); 431*7c478bd9Sstevel@tonic-gate } else { 432*7c478bd9Sstevel@tonic-gate charset += CHARSET_LEN; 433*7c478bd9Sstevel@tonic-gate p = charset; 434*7c478bd9Sstevel@tonic-gate while ((*p != ' ') && (*p != '\t') && 435*7c478bd9Sstevel@tonic-gate (*p != '\n')) 436*7c478bd9Sstevel@tonic-gate p++; 437*7c478bd9Sstevel@tonic-gate len = p - charset; 438*7c478bd9Sstevel@tonic-gate tmp = Xmalloc(len + 1); 439*7c478bd9Sstevel@tonic-gate (void) memcpy(tmp, charset, len); 440*7c478bd9Sstevel@tonic-gate *(tmp + len) = '\0'; 441*7c478bd9Sstevel@tonic-gate charset = tmp; 442*7c478bd9Sstevel@tonic-gate conv_init(charset); 443*7c478bd9Sstevel@tonic-gate free(charset); 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate nplurals = strstr(str->str, NPLURALS_STR); 446*7c478bd9Sstevel@tonic-gate if (nplurals == NULL) { 447*7c478bd9Sstevel@tonic-gate cur_catalog->nplurals = 0; 448*7c478bd9Sstevel@tonic-gate } else { 449*7c478bd9Sstevel@tonic-gate unsigned int num; 450*7c478bd9Sstevel@tonic-gate nplurals += NPLURALS_LEN; 451*7c478bd9Sstevel@tonic-gate p = nplurals; 452*7c478bd9Sstevel@tonic-gate num = 0; 453*7c478bd9Sstevel@tonic-gate while (isdigit((unsigned char)*p)) { 454*7c478bd9Sstevel@tonic-gate num = num * 10 + *p++ - '0'; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate cur_catalog->nplurals = num; 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate if (verbose_flag) 461*7c478bd9Sstevel@tonic-gate check_format(id, str, next_entry_is_c_format); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if (id->pos) 464*7c478bd9Sstevel@tonic-gate free(id->pos); 465*7c478bd9Sstevel@tonic-gate if (str->pos) 466*7c478bd9Sstevel@tonic-gate free(str->pos); 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate msg = cur_catalog->msg; 469*7c478bd9Sstevel@tonic-gate nmsg = cur_catalog->nmsg; 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate msg[nmsg].po = cur_po_index; 472*7c478bd9Sstevel@tonic-gate msg[nmsg].num = id->num; 473*7c478bd9Sstevel@tonic-gate msg[nmsg].id = id->str; 474*7c478bd9Sstevel@tonic-gate msg[nmsg].id_len = id->len; 475*7c478bd9Sstevel@tonic-gate msg[nmsg].str = str->str; 476*7c478bd9Sstevel@tonic-gate msg[nmsg].str_len = str->len; 477*7c478bd9Sstevel@tonic-gate msg[nmsg].hash = hash_val; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate thash_idx = get_hash_index(cur_catalog->thash, 480*7c478bd9Sstevel@tonic-gate hash_val, cur_catalog->thash_size); 481*7c478bd9Sstevel@tonic-gate cur_catalog->thash[thash_idx] = nmsg + 1; 482*7c478bd9Sstevel@tonic-gate cur_catalog->nmsg++; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate if (cur_catalog->nmsg >= cur_catalog->msg_size) { 485*7c478bd9Sstevel@tonic-gate /* no vacancy in message array */ 486*7c478bd9Sstevel@tonic-gate cur_catalog->msg_size += DEF_MSG_NUM; 487*7c478bd9Sstevel@tonic-gate cur_catalog->msg = Xrealloc(cur_catalog->msg, 488*7c478bd9Sstevel@tonic-gate cur_catalog->msg_size * sizeof (struct messages)); 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate cur_catalog->thash_size = 491*7c478bd9Sstevel@tonic-gate find_prime(cur_catalog->msg_size); 492*7c478bd9Sstevel@tonic-gate free(cur_catalog->thash); 493*7c478bd9Sstevel@tonic-gate cur_catalog->thash = Xcalloc(cur_catalog->thash_size, 494*7c478bd9Sstevel@tonic-gate sizeof (unsigned int)); 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate for (n = 0; n < cur_catalog->nmsg; n++) { 497*7c478bd9Sstevel@tonic-gate thash_idx = get_hash_index(cur_catalog->thash, 498*7c478bd9Sstevel@tonic-gate cur_catalog->msg[n].hash, 499*7c478bd9Sstevel@tonic-gate cur_catalog->thash_size); 500*7c478bd9Sstevel@tonic-gate cur_catalog->thash[thash_idx] = n + 1; 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate void 506*7c478bd9Sstevel@tonic-gate po_init(const char *file) 507*7c478bd9Sstevel@tonic-gate { 508*7c478bd9Sstevel@tonic-gate char *filename; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if (!inputdir) { 511*7c478bd9Sstevel@tonic-gate filename = Xstrdup(file); 512*7c478bd9Sstevel@tonic-gate } else { 513*7c478bd9Sstevel@tonic-gate size_t dirlen, filelen, len; 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate dirlen = strlen(inputdir); 516*7c478bd9Sstevel@tonic-gate filelen = strlen(file); 517*7c478bd9Sstevel@tonic-gate len = dirlen + 1 + filelen + 1; 518*7c478bd9Sstevel@tonic-gate filename = Xmalloc(len); 519*7c478bd9Sstevel@tonic-gate (void) memcpy(filename, inputdir, dirlen); 520*7c478bd9Sstevel@tonic-gate *(filename + dirlen) = '/'; 521*7c478bd9Sstevel@tonic-gate (void) memcpy(filename + dirlen + 1, file, filelen); 522*7c478bd9Sstevel@tonic-gate *(filename + dirlen + 1 + filelen) = '\0'; 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate fp = fopen(filename, "r"); 526*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 527*7c478bd9Sstevel@tonic-gate error(gettext(ERR_OPEN_FAILED), filename); 528*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate po_names[cur_po_index] = filename; 532*7c478bd9Sstevel@tonic-gate cur_line = 1; 533*7c478bd9Sstevel@tonic-gate cd = (iconv_t)-1; 534*7c478bd9Sstevel@tonic-gate if (!outfile) 535*7c478bd9Sstevel@tonic-gate cur_mo = NULL; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate void 539*7c478bd9Sstevel@tonic-gate po_fini(void) 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate cur_po_index++; 542*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 543*7c478bd9Sstevel@tonic-gate if (cd != (iconv_t)-1) 544*7c478bd9Sstevel@tonic-gate (void) iconv_close(cd); 545*7c478bd9Sstevel@tonic-gate } 546