1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * 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 2001, 2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "gnu_msgfmt.h" 28 #include "../../lib/libc/inc/msgfmt.h" 29 30 struct messages * 31 search_msg(struct catalog *p, const char *id, unsigned int hash_val) 32 { 33 unsigned int i, idx, inc; 34 struct messages *m; 35 36 idx = hash_val % p->thash_size; 37 inc = 1 + (hash_val % (p->thash_size - 2)); 38 if (!p->thash[idx]) 39 return (NULL); 40 41 m = p->msg; 42 for (m = p->msg; (i = p->thash[idx]) != 0; 43 idx = (idx + inc) % p->thash_size) { 44 if (strcmp(m[i - 1].id, id) == 0) { 45 /* found */ 46 return (&m[i - 1]); 47 } 48 } 49 return (NULL); 50 } 51 52 static int 53 msg_cmp(struct messages *m1, struct messages *m2) 54 { 55 return (strcmp(m1->id, m2->id)); 56 } 57 58 void 59 output_all_gnu_mo_files(void) 60 { 61 struct catalog *p, *op; 62 struct messages *m; 63 size_t id_len, str_len, id_off, str_off, ids_top, strs_top; 64 unsigned int *hash_tbl; 65 unsigned int hash_size; 66 unsigned int num = 0, fnum = 0, unum = 0; 67 unsigned int i, idx; 68 char *ids, *strs; 69 struct msgtbl *id_tbl, *str_tbl; 70 struct gnu_msg_info header; 71 FILE *out; 72 73 p = catalog_head; 74 75 while (p) { 76 num += p->nmsg; 77 fnum += p->fnum; 78 unum += p->unum; 79 80 81 free(p->thash); 82 if (p->nmsg == 0) { 83 /* 84 * no message in this file 85 * skip generating a mo 86 */ 87 goto skip; 88 } 89 90 if (p->header) 91 num--; 92 93 p->msg = (struct messages *)Xrealloc(p->msg, 94 sizeof (struct messages) * p->nmsg); 95 96 /* 97 * Sort the message array 98 */ 99 qsort(p->msg, p->nmsg, sizeof (struct messages), 100 (int (*)(const void *, const void *))msg_cmp); 101 102 103 hash_size = find_prime(p->nmsg); 104 hash_tbl = (unsigned int *)Xcalloc(hash_size, 105 sizeof (unsigned int)); 106 107 108 /* Setting Header info */ 109 header.magic = GNU_MAGIC; 110 header.revision = GNU_REVISION; 111 header.num_of_str = p->nmsg; 112 header.off_msgid_tbl = sizeof (struct gnu_msg_info); 113 header.off_msgstr_tbl = sizeof (struct gnu_msg_info) + 114 p->nmsg * sizeof (struct msgtbl); 115 header.sz_hashtbl = hash_size; 116 header.off_hashtbl = header.off_msgstr_tbl + 117 p->nmsg * sizeof (struct msgtbl); 118 119 m = p->msg; 120 121 id_len = 0; 122 str_len = 0; 123 for (i = 0; i < p->nmsg; i++) { 124 id_len += m[i].id_len; 125 str_len += m[i].str_len; 126 } 127 ids = (char *)Xmalloc(id_len); 128 strs = (char *)Xmalloc(str_len); 129 id_tbl = (struct msgtbl *)Xmalloc(sizeof (struct msgtbl) * 130 p->nmsg); 131 str_tbl = (struct msgtbl *)Xmalloc(sizeof (struct msgtbl) * 132 p->nmsg); 133 id_off = 0; 134 str_off = 0; 135 ids_top = header.off_hashtbl + 136 sizeof (unsigned int) * hash_size; 137 strs_top = ids_top + id_len; 138 for (i = 0; i < p->nmsg; i++) { 139 /* 140 * Set the hash table 141 */ 142 idx = get_hash_index(hash_tbl, m[i].hash, hash_size); 143 hash_tbl[idx] = i + 1; 144 145 /* 146 * rearrange msgid and msgstr 147 */ 148 id_tbl[i].len = m[i].id_len - 1; 149 str_tbl[i].len = m[i].str_len - 1; 150 id_tbl[i].offset = id_off + ids_top; 151 str_tbl[i].offset = str_off + strs_top; 152 (void) memcpy(ids + id_off, m[i].id, m[i].id_len); 153 (void) memcpy(strs + str_off, m[i].str, m[i].str_len); 154 id_off += m[i].id_len; 155 str_off += m[i].str_len; 156 free(m[i].id); 157 free(m[i].str); 158 } 159 160 if ((out = fopen(p->fname, "w")) == NULL) { 161 error(gettext(ERR_OPEN_FAILED), p->fname); 162 /* NOTREACHED */ 163 } 164 165 /* writing header */ 166 (void) fwrite(&header, sizeof (struct gnu_msg_info), 167 1, out); 168 169 /* writing msgid offset table */ 170 (void) fwrite(id_tbl, sizeof (struct msgtbl), 171 p->nmsg, out); 172 /* writing msgstr offset table */ 173 (void) fwrite(str_tbl, sizeof (struct msgtbl), 174 p->nmsg, out); 175 /* writing hash table */ 176 (void) fwrite(hash_tbl, sizeof (unsigned int), 177 hash_size, out); 178 /* writing msgid table */ 179 (void) fwrite(ids, id_len, 1, out); 180 /* writing msgstr table */ 181 (void) fwrite(strs, str_len, 1, out); 182 183 (void) fclose(out); 184 free(id_tbl); 185 free(str_tbl); 186 free(hash_tbl); 187 free(ids); 188 free(strs); 189 skip: 190 free(p->fname); 191 free(p->msg); 192 op = p->next; 193 free(p); 194 p = op; 195 } 196 if (verbose_flag) { 197 diag(gettext(DIAG_RESULTS), num, fnum, unum); 198 } 199 } 200