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